summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/filesystems/mount_api.rst4
-rw-r--r--arch/arm64/kernel/sys32.c2
-rw-r--r--arch/mips/kernel/linux32.c2
-rw-r--r--arch/parisc/kernel/sys_parisc.c4
-rw-r--r--arch/powerpc/kernel/sys_ppc32.c2
-rw-r--r--arch/sparc/kernel/sys_sparc32.c2
-rw-r--r--arch/x86/kernel/sys_ia32.c3
-rw-r--r--fs/adfs/adfs.h4
-rw-r--r--fs/adfs/dir.c2
-rw-r--r--fs/adfs/file.c2
-rw-r--r--fs/adfs/inode.c6
-rw-r--r--fs/affs/affs.h2
-rw-r--r--fs/affs/dir.c2
-rw-r--r--fs/affs/file.c2
-rw-r--r--fs/affs/inode.c5
-rw-r--r--fs/affs/symlink.c2
-rw-r--r--fs/attr.c6
-rw-r--r--fs/autofs/root.c8
-rw-r--r--fs/coredump.c5
-rw-r--r--fs/d_path.c11
-rw-r--r--fs/dcache.c4
-rw-r--r--fs/file.c2
-rw-r--r--fs/file_table.c31
-rw-r--r--fs/fs_context.c1
-rw-r--r--fs/fs_parser.c19
-rw-r--r--fs/hfs/inode.c21
-rw-r--r--fs/internal.h3
-rw-r--r--fs/mbcache.c1
-rw-r--r--fs/namei.c2
-rw-r--r--fs/omfs/inode.c6
-rw-r--r--fs/open.c40
-rw-r--r--fs/proc/base.c22
-rw-r--r--fs/proc/fd.c6
-rw-r--r--fs/proc/generic.c8
-rw-r--r--fs/proc/internal.h4
-rw-r--r--fs/proc/namespaces.c4
-rw-r--r--fs/proc/proc_net.c2
-rw-r--r--fs/readdir.c103
-rw-r--r--fs/select.c35
-rw-r--r--include/asm-generic/vmlinux.lds.h4
-rw-r--r--include/linux/backing-dev-defs.h2
-rw-r--r--include/linux/blkdev.h1
-rw-r--r--include/linux/fs.h3
-rw-r--r--include/linux/fs_parser.h8
-rw-r--r--include/linux/syscalls.h16
-rw-r--r--include/trace/events/coredump.h45
-rw-r--r--init/initramfs.c2
-rw-r--r--io_uring/truncate.c2
-rw-r--r--kernel/acct.c2
-rw-r--r--tools/testing/selftests/filesystems/devpts_pts.c2
50 files changed, 225 insertions, 252 deletions
diff --git a/Documentation/filesystems/mount_api.rst b/Documentation/filesystems/mount_api.rst
index a064234fed5b..e8b94357b4df 100644
--- a/Documentation/filesystems/mount_api.rst
+++ b/Documentation/filesystems/mount_api.rst
@@ -647,9 +647,7 @@ The members are as follows:
fs_param_is_u64 64-bit unsigned int result->uint_64
fs_param_is_enum Enum value name result->uint_32
fs_param_is_string Arbitrary string param->string
- fs_param_is_blob Binary blob param->blob
fs_param_is_blockdev Blockdev path * Needs lookup
- fs_param_is_path Path * Needs lookup
fs_param_is_fd File descriptor result->int_32
fs_param_is_uid User ID (u32) result->uid
fs_param_is_gid Group ID (u32) result->gid
@@ -681,9 +679,7 @@ The members are as follows:
fsparam_u64() fs_param_is_u64
fsparam_enum() fs_param_is_enum
fsparam_string() fs_param_is_string
- fsparam_blob() fs_param_is_blob
fsparam_bdev() fs_param_is_blockdev
- fsparam_path() fs_param_is_path
fsparam_fd() fs_param_is_fd
fsparam_uid() fs_param_is_uid
fsparam_gid() fs_param_is_gid
diff --git a/arch/arm64/kernel/sys32.c b/arch/arm64/kernel/sys32.c
index 96bcfb907443..12a948f3a504 100644
--- a/arch/arm64/kernel/sys32.c
+++ b/arch/arm64/kernel/sys32.c
@@ -89,7 +89,7 @@ COMPAT_SYSCALL_DEFINE4(aarch32_truncate64, const char __user *, pathname,
COMPAT_SYSCALL_DEFINE4(aarch32_ftruncate64, unsigned int, fd, u32, __pad,
arg_u32p(length))
{
- return ksys_ftruncate(fd, arg_u64(length));
+ return ksys_ftruncate(fd, arg_u64(length), FTRUNCATE_LFS);
}
COMPAT_SYSCALL_DEFINE5(aarch32_readahead, int, fd, u32, __pad,
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
index a0c0a7a654e9..fe9a787db569 100644
--- a/arch/mips/kernel/linux32.c
+++ b/arch/mips/kernel/linux32.c
@@ -60,7 +60,7 @@ SYSCALL_DEFINE4(32_truncate64, const char __user *, path,
SYSCALL_DEFINE4(32_ftruncate64, unsigned long, fd, unsigned long, __dummy,
unsigned long, a2, unsigned long, a3)
{
- return ksys_ftruncate(fd, merge_64(a2, a3));
+ return ksys_ftruncate(fd, merge_64(a2, a3), FTRUNCATE_LFS);
}
SYSCALL_DEFINE5(32_llseek, unsigned int, fd, unsigned int, offset_high,
diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c
index b2cdbb8a12b1..fcb0d8069139 100644
--- a/arch/parisc/kernel/sys_parisc.c
+++ b/arch/parisc/kernel/sys_parisc.c
@@ -216,7 +216,7 @@ asmlinkage long parisc_truncate64(const char __user * path,
asmlinkage long parisc_ftruncate64(unsigned int fd,
unsigned int high, unsigned int low)
{
- return ksys_ftruncate(fd, (long)high << 32 | low);
+ return ksys_ftruncate(fd, (long)high << 32 | low, FTRUNCATE_LFS);
}
/* stubs for the benefit of the syscall_table since truncate64 and truncate
@@ -227,7 +227,7 @@ asmlinkage long sys_truncate64(const char __user * path, unsigned long length)
}
asmlinkage long sys_ftruncate64(unsigned int fd, unsigned long length)
{
- return ksys_ftruncate(fd, length);
+ return ksys_ftruncate(fd, length, FTRUNCATE_LFS);
}
asmlinkage long sys_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg)
{
diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c
index d451a8229223..03fa487f2614 100644
--- a/arch/powerpc/kernel/sys_ppc32.c
+++ b/arch/powerpc/kernel/sys_ppc32.c
@@ -101,7 +101,7 @@ PPC32_SYSCALL_DEFINE4(ppc_ftruncate64,
unsigned int, fd, u32, reg4,
unsigned long, len1, unsigned long, len2)
{
- return ksys_ftruncate(fd, merge_64(len1, len2));
+ return ksys_ftruncate(fd, merge_64(len1, len2), FTRUNCATE_LFS);
}
PPC32_SYSCALL_DEFINE6(ppc32_fadvise64,
diff --git a/arch/sparc/kernel/sys_sparc32.c b/arch/sparc/kernel/sys_sparc32.c
index f84a02ab6bf9..04432b82b9e3 100644
--- a/arch/sparc/kernel/sys_sparc32.c
+++ b/arch/sparc/kernel/sys_sparc32.c
@@ -58,7 +58,7 @@ COMPAT_SYSCALL_DEFINE3(truncate64, const char __user *, path, u32, high, u32, lo
COMPAT_SYSCALL_DEFINE3(ftruncate64, unsigned int, fd, u32, high, u32, low)
{
- return ksys_ftruncate(fd, ((u64)high << 32) | low);
+ return ksys_ftruncate(fd, ((u64)high << 32) | low, FTRUNCATE_LFS);
}
static int cp_compat_stat64(struct kstat *stat,
diff --git a/arch/x86/kernel/sys_ia32.c b/arch/x86/kernel/sys_ia32.c
index 6cf65397d225..610a1c2f4519 100644
--- a/arch/x86/kernel/sys_ia32.c
+++ b/arch/x86/kernel/sys_ia32.c
@@ -61,7 +61,8 @@ SYSCALL_DEFINE3(ia32_truncate64, const char __user *, filename,
SYSCALL_DEFINE3(ia32_ftruncate64, unsigned int, fd,
unsigned long, offset_low, unsigned long, offset_high)
{
- return ksys_ftruncate(fd, ((loff_t) offset_high << 32) | offset_low);
+ return ksys_ftruncate(fd, ((loff_t) offset_high << 32) | offset_low,
+ FTRUNCATE_LFS);
}
/* warning: next two assume little endian */
diff --git a/fs/adfs/adfs.h b/fs/adfs/adfs.h
index 223f0283d20f..0d32b7cd99b4 100644
--- a/fs/adfs/adfs.h
+++ b/fs/adfs/adfs.h
@@ -144,8 +144,8 @@ struct adfs_discmap {
/* Inode stuff */
struct inode *adfs_iget(struct super_block *sb, struct object_info *obj);
int adfs_write_inode(struct inode *inode, struct writeback_control *wbc);
-int adfs_notify_change(struct mnt_idmap *idmap, struct dentry *dentry,
- struct iattr *attr);
+int adfs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
+ struct iattr *attr);
/* map.c */
int adfs_map_lookup(struct super_block *sb, u32 frag_id, unsigned int offset);
diff --git a/fs/adfs/dir.c b/fs/adfs/dir.c
index b8e23e8124ed..11afa9e157aa 100644
--- a/fs/adfs/dir.c
+++ b/fs/adfs/dir.c
@@ -454,5 +454,5 @@ adfs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
*/
const struct inode_operations adfs_dir_inode_operations = {
.lookup = adfs_lookup,
- .setattr = adfs_notify_change,
+ .setattr = adfs_setattr,
};
diff --git a/fs/adfs/file.c b/fs/adfs/file.c
index 4a1828b3f88f..d056d48c637c 100644
--- a/fs/adfs/file.c
+++ b/fs/adfs/file.c
@@ -32,5 +32,5 @@ const struct file_operations adfs_file_operations = {
};
const struct inode_operations adfs_file_inode_operations = {
- .setattr = adfs_notify_change,
+ .setattr = adfs_setattr,
};
diff --git a/fs/adfs/inode.c b/fs/adfs/inode.c
index 6830f8bc8d4e..4ac442d0a8c0 100644
--- a/fs/adfs/inode.c
+++ b/fs/adfs/inode.c
@@ -299,8 +299,7 @@ out:
* later.
*/
int
-adfs_notify_change(struct mnt_idmap *idmap, struct dentry *dentry,
- struct iattr *attr)
+adfs_setattr(struct mnt_idmap *idmap, struct dentry *dentry, struct iattr *attr)
{
struct inode *inode = d_inode(dentry);
struct super_block *sb = inode->i_sb;
@@ -355,8 +354,7 @@ out:
/*
* write an existing inode back to the directory, and therefore the disk.
- * The adfs-specific inode data has already been updated by
- * adfs_notify_change()
+ * The adfs-specific inode data has already been updated by * adfs_setattr().
*/
int adfs_write_inode(struct inode *inode, struct writeback_control *wbc)
{
diff --git a/fs/affs/affs.h b/fs/affs/affs.h
index a1eb400e1018..a0caf6ace860 100644
--- a/fs/affs/affs.h
+++ b/fs/affs/affs.h
@@ -186,7 +186,7 @@ extern int affs_rename2(struct mnt_idmap *idmap,
/* inode.c */
extern struct inode *affs_new_inode(struct inode *dir);
-extern int affs_notify_change(struct mnt_idmap *idmap,
+extern int affs_setattr(struct mnt_idmap *idmap,
struct dentry *dentry, struct iattr *attr);
extern void affs_evict_inode(struct inode *inode);
extern struct inode *affs_iget(struct super_block *sb,
diff --git a/fs/affs/dir.c b/fs/affs/dir.c
index 11e2bac2e391..192dac468f79 100644
--- a/fs/affs/dir.c
+++ b/fs/affs/dir.c
@@ -71,7 +71,7 @@ const struct inode_operations affs_dir_inode_operations = {
.mkdir = affs_mkdir,
.rmdir = affs_rmdir,
.rename = affs_rename2,
- .setattr = affs_notify_change,
+ .setattr = affs_setattr,
};
static int
diff --git a/fs/affs/file.c b/fs/affs/file.c
index 2e93491484a9..144b17482d12 100644
--- a/fs/affs/file.c
+++ b/fs/affs/file.c
@@ -1016,5 +1016,5 @@ const struct file_operations affs_file_operations = {
};
const struct inode_operations affs_file_inode_operations = {
- .setattr = affs_notify_change,
+ .setattr = affs_setattr,
};
diff --git a/fs/affs/inode.c b/fs/affs/inode.c
index e03e9f109ff9..5dd1b016bcb0 100644
--- a/fs/affs/inode.c
+++ b/fs/affs/inode.c
@@ -213,13 +213,12 @@ affs_write_inode(struct inode *inode, struct writeback_control *wbc)
}
int
-affs_notify_change(struct mnt_idmap *idmap, struct dentry *dentry,
- struct iattr *attr)
+affs_setattr(struct mnt_idmap *idmap, struct dentry *dentry, struct iattr *attr)
{
struct inode *inode = d_inode(dentry);
int error;
- pr_debug("notify_change(%llu,0x%x)\n", inode->i_ino, attr->ia_valid);
+ pr_debug("setattr(%llu,0x%x)\n", inode->i_ino, attr->ia_valid);
error = setattr_prepare(&nop_mnt_idmap, dentry, attr);
if (error)
diff --git a/fs/affs/symlink.c b/fs/affs/symlink.c
index de31ed2e71df..4994abb97ab7 100644
--- a/fs/affs/symlink.c
+++ b/fs/affs/symlink.c
@@ -71,5 +71,5 @@ const struct address_space_operations affs_symlink_aops = {
const struct inode_operations affs_symlink_inode_operations = {
.get_link = page_get_link,
- .setattr = affs_notify_change,
+ .setattr = affs_setattr,
};
diff --git a/fs/attr.c b/fs/attr.c
index e7d7c6d19fe9..ded221defae6 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -46,8 +46,8 @@ int setattr_should_drop_sgid(struct mnt_idmap *idmap,
EXPORT_SYMBOL(setattr_should_drop_sgid);
/**
- * setattr_should_drop_suidgid - determine whether the set{g,u}id bit needs to
- * be dropped
+ * setattr_should_drop_suidgid - determine whether the set{g,u}id bit
+ * needs to be dropped
* @idmap: idmap of the mount @inode was found from
* @inode: inode to check
*
@@ -165,7 +165,7 @@ int setattr_prepare(struct mnt_idmap *idmap, struct dentry *dentry,
unsigned int ia_valid = attr->ia_valid;
/*
- * First check size constraints. These can't be overriden using
+ * First check size constraints. These can't be overridden using
* ATTR_FORCE.
*/
if (ia_valid & ATTR_SIZE) {
diff --git a/fs/autofs/root.c b/fs/autofs/root.c
index 2c31002b314a..186e960f1e23 100644
--- a/fs/autofs/root.c
+++ b/fs/autofs/root.c
@@ -7,6 +7,7 @@
#include <linux/capability.h>
#include <linux/compat.h>
+#include <linux/string.h>
#include "autofs_i.h"
@@ -578,7 +579,6 @@ static int autofs_dir_symlink(struct mnt_idmap *idmap,
struct autofs_info *ino = autofs_dentry_ino(dentry);
struct autofs_info *p_ino;
struct inode *inode;
- size_t size = strlen(symname);
char *cp;
pr_debug("%s <- %pd\n", symname, dentry);
@@ -589,19 +589,17 @@ static int autofs_dir_symlink(struct mnt_idmap *idmap,
autofs_del_active(dentry);
- cp = kmalloc(size + 1, GFP_KERNEL);
+ cp = kstrdup(symname, GFP_KERNEL);
if (!cp)
return -ENOMEM;
- strcpy(cp, symname);
-
inode = autofs_get_inode(dir->i_sb, S_IFLNK | 0555);
if (!inode) {
kfree(cp);
return -ENOMEM;
}
inode->i_private = cp;
- inode->i_size = size;
+ inode->i_size = strlen(cp);
d_make_persistent(dentry, inode);
p_ino = autofs_dentry_ino(dentry->d_parent);
diff --git a/fs/coredump.c b/fs/coredump.c
index 29df8aa19e2e..bb6fdb1f458e 100644
--- a/fs/coredump.c
+++ b/fs/coredump.c
@@ -63,6 +63,9 @@
#include <trace/events/sched.h>
+#define CREATE_TRACE_POINTS
+#include <trace/events/coredump.h>
+
static bool dump_vma_snapshot(struct coredump_params *cprm);
static void free_vma_snapshot(struct coredump_params *cprm);
@@ -1090,6 +1093,8 @@ static inline bool coredump_skip(const struct coredump_params *cprm,
static void do_coredump(struct core_name *cn, struct coredump_params *cprm,
size_t **argv, int *argc, const struct linux_binfmt *binfmt)
{
+ trace_coredump(cprm->siginfo->si_signo);
+
if (!coredump_parse(cn, cprm, argv, argc)) {
coredump_report_failure("format_corename failed, aborting core");
return;
diff --git a/fs/d_path.c b/fs/d_path.c
index bb365511066b..a48957c0971e 100644
--- a/fs/d_path.c
+++ b/fs/d_path.c
@@ -301,18 +301,19 @@ EXPORT_SYMBOL(d_path);
char *dynamic_dname(char *buffer, int buflen, const char *fmt, ...)
{
va_list args;
- char temp[64];
+ char *start;
int sz;
va_start(args, fmt);
- sz = vsnprintf(temp, sizeof(temp), fmt, args) + 1;
+ sz = vsnprintf(buffer, buflen, fmt, args) + 1;
va_end(args);
- if (sz > sizeof(temp) || sz > buflen)
+ if (sz > NAME_MAX || sz > buflen)
return ERR_PTR(-ENAMETOOLONG);
- buffer += buflen - sz;
- return memcpy(buffer, temp, sz);
+ /* Move the formatted d_name to the end of the buffer. */
+ start = buffer + (buflen - sz);
+ return memmove(start, buffer, sz);
}
char *simple_dname(struct dentry *dentry, char *buffer, int buflen)
diff --git a/fs/dcache.c b/fs/dcache.c
index 0a4ffda07360..9ceab142896f 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -3257,7 +3257,7 @@ static void __init dcache_init_early(void)
HASH_EARLY | HASH_ZERO,
&d_hash_shift,
NULL,
- 0,
+ 2,
0);
d_hash_shift = 32 - d_hash_shift;
@@ -3289,7 +3289,7 @@ static void __init dcache_init(void)
HASH_ZERO,
&d_hash_shift,
NULL,
- 0,
+ 2,
0);
d_hash_shift = 32 - d_hash_shift;
diff --git a/fs/file.c b/fs/file.c
index 384c83ce768d..2c81c0b162d0 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -200,7 +200,7 @@ static struct fdtable *alloc_fdtable(unsigned int slots_wanted)
/*
* Check if the allocation size would exceed INT_MAX. kvmalloc_array()
* and kvmalloc() will warn if the allocation size is greater than
- * INT_MAX, as filp_cachep objects are not __GFP_NOWARN.
+ * INT_MAX, as filp_cache objects are not __GFP_NOWARN.
*
* This can happen when sysctl_nr_open is set to a very high value and
* a process tries to use a file descriptor near that limit. For example,
diff --git a/fs/file_table.c b/fs/file_table.c
index aaa5faaace1e..c40ec1be2899 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -30,6 +30,8 @@
#include <linux/atomic.h>
+#include <asm/runtime-const.h>
+
#include "internal.h"
/* sysctl tunables... */
@@ -38,8 +40,10 @@ static struct files_stat_struct files_stat = {
};
/* SLAB cache for file structures */
-static struct kmem_cache *filp_cachep __ro_after_init;
-static struct kmem_cache *bfilp_cachep __ro_after_init;
+static struct kmem_cache *__filp_cache __ro_after_init;
+#define filp_cache runtime_const_ptr(__filp_cache)
+static struct kmem_cache *__bfilp_cache __ro_after_init;
+#define bfilp_cache runtime_const_ptr(__bfilp_cache)
static struct percpu_counter nr_files __cacheline_aligned_in_smp;
@@ -74,9 +78,9 @@ static inline void file_free(struct file *f)
put_cred(f->f_cred);
if (unlikely(f->f_mode & FMODE_BACKING)) {
path_put(backing_file_user_path(f));
- kmem_cache_free(bfilp_cachep, backing_file(f));
+ kmem_cache_free(bfilp_cache, backing_file(f));
} else {
- kmem_cache_free(filp_cachep, f);
+ kmem_cache_free(filp_cache, f);
}
}
@@ -234,13 +238,13 @@ struct file *alloc_empty_file(int flags, const struct cred *cred)
goto over;
}
- f = kmem_cache_alloc(filp_cachep, GFP_KERNEL);
+ f = kmem_cache_alloc(filp_cache, GFP_KERNEL);
if (unlikely(!f))
return ERR_PTR(-ENOMEM);
error = init_file(f, flags, cred);
if (unlikely(error)) {
- kmem_cache_free(filp_cachep, f);
+ kmem_cache_free(filp_cache, f);
return ERR_PTR(error);
}
@@ -268,13 +272,13 @@ struct file *alloc_empty_file_noaccount(int flags, const struct cred *cred)
struct file *f;
int error;
- f = kmem_cache_alloc(filp_cachep, GFP_KERNEL);
+ f = kmem_cache_alloc(filp_cache, GFP_KERNEL);
if (unlikely(!f))
return ERR_PTR(-ENOMEM);
error = init_file(f, flags, cred);
if (unlikely(error)) {
- kmem_cache_free(filp_cachep, f);
+ kmem_cache_free(filp_cache, f);
return ERR_PTR(error);
}
@@ -295,13 +299,13 @@ struct file *alloc_empty_backing_file(int flags, const struct cred *cred)
struct backing_file *ff;
int error;
- ff = kmem_cache_alloc(bfilp_cachep, GFP_KERNEL);
+ ff = kmem_cache_alloc(bfilp_cache, GFP_KERNEL);
if (unlikely(!ff))
return ERR_PTR(-ENOMEM);
error = init_file(&ff->file, flags, cred);
if (unlikely(error)) {
- kmem_cache_free(bfilp_cachep, ff);
+ kmem_cache_free(bfilp_cache, ff);
return ERR_PTR(error);
}
@@ -593,14 +597,17 @@ void __init files_init(void)
.freeptr_offset = offsetof(struct file, f_freeptr),
};
- filp_cachep = kmem_cache_create("filp", sizeof(struct file), &args,
+ __filp_cache = kmem_cache_create("filp", sizeof(struct file), &args,
SLAB_HWCACHE_ALIGN | SLAB_PANIC |
SLAB_ACCOUNT | SLAB_TYPESAFE_BY_RCU);
+ runtime_const_init(ptr, __filp_cache);
args.freeptr_offset = offsetof(struct backing_file, bf_freeptr);
- bfilp_cachep = kmem_cache_create("bfilp", sizeof(struct backing_file),
+ __bfilp_cache = kmem_cache_create("bfilp", sizeof(struct backing_file),
&args, SLAB_HWCACHE_ALIGN | SLAB_PANIC |
SLAB_ACCOUNT | SLAB_TYPESAFE_BY_RCU);
+ runtime_const_init(ptr, __bfilp_cache);
+
percpu_counter_init(&nr_files, 0, GFP_KERNEL);
}
diff --git a/fs/fs_context.c b/fs/fs_context.c
index a37b0a093505..23ad66cd94e1 100644
--- a/fs/fs_context.c
+++ b/fs/fs_context.c
@@ -318,7 +318,6 @@ struct fs_context *fs_context_for_reconfigure(struct dentry *dentry,
return alloc_fs_context(dentry->d_sb->s_type, dentry, sb_flags,
sb_flags_mask, FS_CONTEXT_FOR_RECONFIGURE);
}
-EXPORT_SYMBOL(fs_context_for_reconfigure);
/**
* fs_context_for_submount: allocate a new fs_context for a submount
diff --git a/fs/fs_parser.c b/fs/fs_parser.c
index c092a9f79e32..b4cc4cce518a 100644
--- a/fs/fs_parser.c
+++ b/fs/fs_parser.c
@@ -13,7 +13,7 @@
#include <linux/namei.h>
#include "internal.h"
-const struct constant_table bool_names[] = {
+static const struct constant_table bool_names[] = {
{ "0", false },
{ "1", true },
{ "false", false },
@@ -22,7 +22,6 @@ const struct constant_table bool_names[] = {
{ "yes", true },
{ },
};
-EXPORT_SYMBOL(bool_names);
static const struct constant_table *
__lookup_constant(const struct constant_table *tbl, const char *name)
@@ -278,15 +277,6 @@ int fs_param_is_string(struct p_log *log, const struct fs_parameter_spec *p,
}
EXPORT_SYMBOL(fs_param_is_string);
-int fs_param_is_blob(struct p_log *log, const struct fs_parameter_spec *p,
- struct fs_parameter *param, struct fs_parse_result *result)
-{
- if (param->type != fs_value_is_blob)
- return fs_param_bad_value(log, param);
- return 0;
-}
-EXPORT_SYMBOL(fs_param_is_blob);
-
int fs_param_is_fd(struct p_log *log, const struct fs_parameter_spec *p,
struct fs_parameter *param, struct fs_parse_result *result)
{
@@ -371,13 +361,6 @@ int fs_param_is_blockdev(struct p_log *log, const struct fs_parameter_spec *p,
}
EXPORT_SYMBOL(fs_param_is_blockdev);
-int fs_param_is_path(struct p_log *log, const struct fs_parameter_spec *p,
- struct fs_parameter *param, struct fs_parse_result *result)
-{
- return 0;
-}
-EXPORT_SYMBOL(fs_param_is_path);
-
#ifdef CONFIG_VALIDATE_FS_PARSER
/**
* fs_validate_description - Validate a parameter specification array
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index 95f0333a608b..89b33a9d46d5 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -622,23 +622,6 @@ static int hfs_file_release(struct inode *inode, struct file *file)
return 0;
}
-/*
- * hfs_notify_change()
- *
- * Based very closely on fs/msdos/inode.c by Werner Almesberger
- *
- * This is the notify_change() field in the super_operations structure
- * for HFS file systems. The purpose is to take that changes made to
- * an inode and apply then in a filesystem-dependent manner. In this
- * case the process has a few of tasks to do:
- * 1) prevent changes to the i_uid and i_gid fields.
- * 2) map file permissions to the closest allowable permissions
- * 3) Since multiple Linux files can share the same on-disk inode under
- * HFS (for instance the data and resource forks of a file) a change
- * to permissions must be applied to all other in-core inodes which
- * correspond to the same HFS file.
- */
-
int hfs_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
struct iattr *attr)
{
@@ -646,8 +629,7 @@ int hfs_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
struct hfs_sb_info *hsb = HFS_SB(inode->i_sb);
int error;
- error = setattr_prepare(&nop_mnt_idmap, dentry,
- attr); /* basic permission checks */
+ error = setattr_prepare(&nop_mnt_idmap, dentry, attr);
if (error)
return error;
@@ -663,6 +645,7 @@ int hfs_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
return hsb->s_quiet ? 0 : error;
}
+ /* map file permissions to the closest allowable permissions in HFS */
if (attr->ia_valid & ATTR_MODE) {
/* Only the 'w' bits can ever change and only all together. */
if (attr->ia_mode & S_IWUSR)
diff --git a/fs/internal.h b/fs/internal.h
index cbc384a1aa09..52e4c354e7a4 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -198,8 +198,7 @@ extern struct open_how build_open_how(int flags, umode_t mode);
extern int build_open_flags(const struct open_how *how, struct open_flags *op);
struct file *file_close_fd_locked(struct files_struct *files, unsigned fd);
-int do_ftruncate(struct file *file, loff_t length, int small);
-int do_sys_ftruncate(unsigned int fd, loff_t length, int small);
+int do_ftruncate(struct file *file, loff_t length, unsigned int flags);
int chmod_common(const struct path *path, umode_t mode);
int do_fchownat(int dfd, const char __user *filename, uid_t user, gid_t group,
int flag);
diff --git a/fs/mbcache.c b/fs/mbcache.c
index 480d02d6ebf0..2a6319b4072c 100644
--- a/fs/mbcache.c
+++ b/fs/mbcache.c
@@ -406,6 +406,7 @@ void mb_cache_destroy(struct mb_cache *cache)
{
struct mb_cache_entry *entry, *next;
+ cancel_work_sync(&cache->c_shrink_work);
shrinker_free(cache->c_shrink);
/*
diff --git a/fs/namei.c b/fs/namei.c
index 2113958c3b7a..c7fac83c9a85 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2140,7 +2140,7 @@ static __always_inline const char *step_into(struct nameidata *nd, int flags,
if (unlikely(!inode))
return ERR_PTR(-ENOENT);
nd->path.dentry = dentry;
- /* nd->path.mnt is retained on purpose */
+ /* nd->path.mnt remains unchanged as no mount point was crossed */
nd->inode = inode;
nd->seq = nd->next_seq;
return NULL;
diff --git a/fs/omfs/inode.c b/fs/omfs/inode.c
index 90ae07c69349..834cae1e6223 100644
--- a/fs/omfs/inode.c
+++ b/fs/omfs/inode.c
@@ -513,6 +513,12 @@ static int omfs_fill_super(struct super_block *sb, struct fs_context *fc)
goto out_brelse_bh;
}
+ if (sbi->s_sys_blocksize < OMFS_DIR_START) {
+ printk(KERN_ERR "omfs: sysblock size (%d) is too small\n",
+ sbi->s_sys_blocksize);
+ goto out_brelse_bh;
+ }
+
if (sbi->s_blocksize < sbi->s_sys_blocksize ||
sbi->s_blocksize > OMFS_MAX_BLOCK_SIZE) {
printk(KERN_ERR "omfs: block size (%d) is out of range\n",
diff --git a/fs/open.c b/fs/open.c
index 91f1139591ab..681d405bc61e 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -126,7 +126,7 @@ mnt_drop_write_and_out:
}
EXPORT_SYMBOL_GPL(vfs_truncate);
-int do_sys_truncate(const char __user *pathname, loff_t length)
+int ksys_truncate(const char __user *pathname, loff_t length)
{
unsigned int lookup_flags = LOOKUP_FOLLOW;
struct path path;
@@ -151,33 +151,31 @@ retry:
SYSCALL_DEFINE2(truncate, const char __user *, path, long, length)
{
- return do_sys_truncate(path, length);
+ return ksys_truncate(path, length);
}
#ifdef CONFIG_COMPAT
COMPAT_SYSCALL_DEFINE2(truncate, const char __user *, path, compat_off_t, length)
{
- return do_sys_truncate(path, length);
+ return ksys_truncate(path, length);
}
#endif
-int do_ftruncate(struct file *file, loff_t length, int small)
+int do_ftruncate(struct file *file, loff_t length, unsigned int flags)
{
- struct inode *inode;
- struct dentry *dentry;
+ struct dentry *dentry = file->f_path.dentry;
+ struct inode *inode = dentry->d_inode;
int error;
- /* explicitly opened as large or we are on 64-bit box */
- if (file->f_flags & O_LARGEFILE)
- small = 0;
-
- dentry = file->f_path.dentry;
- inode = dentry->d_inode;
if (!S_ISREG(inode->i_mode) || !(file->f_mode & FMODE_WRITE))
return -EINVAL;
- /* Cannot ftruncate over 2^31 bytes without large file support */
- if (small && length > MAX_NON_LFS)
+ /*
+ * Cannot ftruncate over 2^31 bytes without large file support, either
+ * through opening with O_LARGEFILE or by using ftruncate64().
+ */
+ if (length > MAX_NON_LFS &&
+ !(file->f_flags & O_LARGEFILE) && !(flags & FTRUNCATE_LFS))
return -EINVAL;
/* Check IS_APPEND on real upper inode */
@@ -197,7 +195,7 @@ int do_ftruncate(struct file *file, loff_t length, int small)
ATTR_MTIME | ATTR_CTIME, file);
}
-int do_sys_ftruncate(unsigned int fd, loff_t length, int small)
+int ksys_ftruncate(unsigned int fd, loff_t length, unsigned int flags)
{
if (length < 0)
return -EINVAL;
@@ -205,18 +203,18 @@ int do_sys_ftruncate(unsigned int fd, loff_t length, int small)
if (fd_empty(f))
return -EBADF;
- return do_ftruncate(fd_file(f), length, small);
+ return do_ftruncate(fd_file(f), length, flags);
}
SYSCALL_DEFINE2(ftruncate, unsigned int, fd, off_t, length)
{
- return do_sys_ftruncate(fd, length, 1);
+ return ksys_ftruncate(fd, length, 0);
}
#ifdef CONFIG_COMPAT
COMPAT_SYSCALL_DEFINE2(ftruncate, unsigned int, fd, compat_off_t, length)
{
- return do_sys_ftruncate(fd, length, 1);
+ return ksys_ftruncate(fd, length, 0);
}
#endif
@@ -224,12 +222,12 @@ COMPAT_SYSCALL_DEFINE2(ftruncate, unsigned int, fd, compat_off_t, length)
#if BITS_PER_LONG == 32
SYSCALL_DEFINE2(truncate64, const char __user *, path, loff_t, length)
{
- return do_sys_truncate(path, length);
+ return ksys_truncate(path, length);
}
SYSCALL_DEFINE2(ftruncate64, unsigned int, fd, loff_t, length)
{
- return do_sys_ftruncate(fd, length, 0);
+ return ksys_ftruncate(fd, length, FTRUNCATE_LFS);
}
#endif /* BITS_PER_LONG == 32 */
@@ -245,7 +243,7 @@ COMPAT_SYSCALL_DEFINE3(truncate64, const char __user *, pathname,
COMPAT_SYSCALL_DEFINE3(ftruncate64, unsigned int, fd,
compat_arg_u64_dual(length))
{
- return ksys_ftruncate(fd, compat_arg_u64_glue(length));
+ return ksys_ftruncate(fd, compat_arg_u64_glue(length), FTRUNCATE_LFS);
}
#endif
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 4c863d17dfb4..d9acfa89c894 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -721,7 +721,7 @@ static bool proc_fd_access_allowed(struct inode *inode)
return allowed;
}
-int proc_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
+int proc_nochmod_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
struct iattr *attr)
{
int error;
@@ -794,7 +794,7 @@ static int proc_pid_permission(struct mnt_idmap *idmap,
static const struct inode_operations proc_def_inode_operations = {
- .setattr = proc_setattr,
+ .setattr = proc_nochmod_setattr,
};
static int proc_single_show(struct seq_file *m, void *v)
@@ -1866,7 +1866,7 @@ out:
const struct inode_operations proc_pid_link_inode_operations = {
.readlink = proc_pid_readlink,
.get_link = proc_pid_get_link,
- .setattr = proc_setattr,
+ .setattr = proc_nochmod_setattr,
};
@@ -2319,7 +2319,7 @@ proc_map_files_get_link(struct dentry *dentry,
static const struct inode_operations proc_map_files_link_inode_operations = {
.readlink = proc_pid_readlink,
.get_link = proc_map_files_get_link,
- .setattr = proc_setattr,
+ .setattr = proc_nochmod_setattr,
};
static struct dentry *
@@ -2398,7 +2398,7 @@ out:
static const struct inode_operations proc_map_files_inode_operations = {
.lookup = proc_map_files_lookup,
.permission = proc_fd_permission,
- .setattr = proc_setattr,
+ .setattr = proc_nochmod_setattr,
};
static int
@@ -2885,7 +2885,7 @@ static struct dentry *proc_##LSM##_attr_dir_lookup(struct inode *dir, \
static const struct inode_operations proc_##LSM##_attr_dir_inode_ops = { \
.lookup = proc_##LSM##_attr_dir_lookup, \
.getattr = pid_getattr, \
- .setattr = proc_setattr, \
+ .setattr = proc_nochmod_setattr, \
}
#ifdef CONFIG_SECURITY_SMACK
@@ -2944,7 +2944,7 @@ static struct dentry *proc_attr_dir_lookup(struct inode *dir,
static const struct inode_operations proc_attr_dir_inode_operations = {
.lookup = proc_attr_dir_lookup,
.getattr = pid_getattr,
- .setattr = proc_setattr,
+ .setattr = proc_nochmod_setattr,
};
#endif
@@ -3453,7 +3453,7 @@ static struct dentry *proc_tgid_base_lookup(struct inode *dir, struct dentry *de
static const struct inode_operations proc_tgid_base_inode_operations = {
.lookup = proc_tgid_base_lookup,
.getattr = pid_getattr,
- .setattr = proc_setattr,
+ .setattr = proc_nochmod_setattr,
.permission = proc_pid_permission,
};
@@ -3650,7 +3650,7 @@ static int proc_tid_comm_permission(struct mnt_idmap *idmap,
}
static const struct inode_operations proc_tid_comm_inode_operations = {
- .setattr = proc_setattr,
+ .setattr = proc_nochmod_setattr,
.permission = proc_tid_comm_permission,
};
@@ -3779,7 +3779,7 @@ static const struct file_operations proc_tid_base_operations = {
static const struct inode_operations proc_tid_base_inode_operations = {
.lookup = proc_tid_base_lookup,
.getattr = pid_getattr,
- .setattr = proc_setattr,
+ .setattr = proc_nochmod_setattr,
};
static struct dentry *proc_task_instantiate(struct dentry *dentry,
@@ -3992,7 +3992,7 @@ static loff_t proc_dir_llseek(struct file *file, loff_t offset, int whence)
static const struct inode_operations proc_task_inode_operations = {
.lookup = proc_task_lookup,
.getattr = proc_task_getattr,
- .setattr = proc_setattr,
+ .setattr = proc_nochmod_setattr,
.permission = proc_pid_permission,
};
diff --git a/fs/proc/fd.c b/fs/proc/fd.c
index aae1a83e8846..05c7513e77c7 100644
--- a/fs/proc/fd.c
+++ b/fs/proc/fd.c
@@ -102,7 +102,7 @@ static int proc_fdinfo_permission(struct mnt_idmap *idmap, struct inode *inode,
static const struct inode_operations proc_fdinfo_file_inode_operations = {
.permission = proc_fdinfo_permission,
- .setattr = proc_setattr,
+ .setattr = proc_nochmod_setattr,
};
static const struct file_operations proc_fdinfo_file_operations = {
@@ -361,7 +361,7 @@ const struct inode_operations proc_fd_inode_operations = {
.lookup = proc_lookupfd,
.permission = proc_fd_permission,
.getattr = proc_fd_getattr,
- .setattr = proc_setattr,
+ .setattr = proc_nochmod_setattr,
};
static struct dentry *proc_fdinfo_instantiate(struct dentry *dentry,
@@ -402,7 +402,7 @@ static int proc_fdinfo_iterate(struct file *file, struct dir_context *ctx)
const struct inode_operations proc_fdinfo_inode_operations = {
.lookup = proc_lookupfdinfo,
.permission = proc_fdinfo_permission,
- .setattr = proc_setattr,
+ .setattr = proc_nochmod_setattr,
};
const struct file_operations proc_fdinfo_operations = {
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 501889856461..8bb81e58c9d8 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -115,8 +115,8 @@ static bool pde_subdir_insert(struct proc_dir_entry *dir,
return true;
}
-static int proc_notify_change(struct mnt_idmap *idmap,
- struct dentry *dentry, struct iattr *iattr)
+static int proc_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
+ struct iattr *iattr)
{
struct inode *inode = d_inode(dentry);
struct proc_dir_entry *de = PDE(inode);
@@ -151,7 +151,7 @@ static int proc_getattr(struct mnt_idmap *idmap,
}
static const struct inode_operations proc_file_inode_operations = {
- .setattr = proc_notify_change,
+ .setattr = proc_setattr,
};
/*
@@ -364,7 +364,7 @@ const struct dentry_operations proc_net_dentry_ops = {
static const struct inode_operations proc_dir_inode_operations = {
.lookup = proc_lookup,
.getattr = proc_getattr,
- .setattr = proc_notify_change,
+ .setattr = proc_setattr,
};
static void pde_set_flags(struct proc_dir_entry *pde)
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index c1e8eb984da8..64dc44832808 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -257,8 +257,8 @@ extern int proc_pid_statm(struct seq_file *, struct pid_namespace *,
extern const struct dentry_operations pid_dentry_operations;
extern int pid_getattr(struct mnt_idmap *, const struct path *,
struct kstat *, u32, unsigned int);
-extern int proc_setattr(struct mnt_idmap *, struct dentry *,
- struct iattr *);
+int proc_nochmod_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
+ struct iattr *attr);
extern void proc_pid_evict_inode(struct proc_inode *);
extern struct inode *proc_pid_make_inode(struct super_block *, struct task_struct *, umode_t);
extern void pid_update_inode(struct task_struct *, struct inode *);
diff --git a/fs/proc/namespaces.c b/fs/proc/namespaces.c
index ea2b597fd92c..39f4169f669f 100644
--- a/fs/proc/namespaces.c
+++ b/fs/proc/namespaces.c
@@ -92,7 +92,7 @@ static int proc_ns_readlink(struct dentry *dentry, char __user *buffer, int bufl
static const struct inode_operations proc_ns_link_inode_operations = {
.readlink = proc_ns_readlink,
.get_link = proc_ns_get_link,
- .setattr = proc_setattr,
+ .setattr = proc_nochmod_setattr,
};
static struct dentry *proc_ns_instantiate(struct dentry *dentry,
@@ -178,5 +178,5 @@ out_no_task:
const struct inode_operations proc_ns_dir_inode_operations = {
.lookup = proc_ns_dir_lookup,
.getattr = pid_getattr,
- .setattr = proc_setattr,
+ .setattr = proc_nochmod_setattr,
};
diff --git a/fs/proc/proc_net.c b/fs/proc/proc_net.c
index 52f0b75cbce2..184cddeb8215 100644
--- a/fs/proc/proc_net.c
+++ b/fs/proc/proc_net.c
@@ -322,7 +322,7 @@ static int proc_tgid_net_getattr(struct mnt_idmap *idmap,
const struct inode_operations proc_net_inode_operations = {
.lookup = proc_tgid_net_lookup,
.getattr = proc_tgid_net_getattr,
- .setattr = proc_setattr,
+ .setattr = proc_nochmod_setattr,
};
static int proc_tgid_net_readdir(struct file *file, struct dir_context *ctx)
diff --git a/fs/readdir.c b/fs/readdir.c
index 73707b6816e9..76bb1ae3a450 100644
--- a/fs/readdir.c
+++ b/fs/readdir.c
@@ -22,6 +22,8 @@
#include <linux/compat.h>
#include <linux/uaccess.h>
+#define dirent_size(dirent, len) offsetof(typeof(*(dirent)), d_name[len])
+
/*
* Some filesystems were never converted to '->iterate_shared()'
* and their directory iterators want the inode lock held for
@@ -198,18 +200,13 @@ static bool fillonedir(struct dir_context *ctx, const char *name, int namlen,
}
buf->result++;
dirent = buf->dirent;
- if (!user_write_access_begin(dirent,
- (unsigned long)(dirent->d_name + namlen + 1) -
- (unsigned long)dirent))
- goto efault;
- unsafe_put_user(d_ino, &dirent->d_ino, efault_end);
- unsafe_put_user(offset, &dirent->d_offset, efault_end);
- unsafe_put_user(namlen, &dirent->d_namlen, efault_end);
- unsafe_copy_dirent_name(dirent->d_name, name, namlen, efault_end);
- user_write_access_end();
+ scoped_user_write_access_size(dirent, dirent_size(dirent, namlen + 1), efault) {
+ unsafe_put_user(d_ino, &dirent->d_ino, efault);
+ unsafe_put_user(offset, &dirent->d_offset, efault);
+ unsafe_put_user(namlen, &dirent->d_namlen, efault);
+ unsafe_copy_dirent_name(dirent->d_name, name, namlen, efault);
+ }
return true;
-efault_end:
- user_write_access_end();
efault:
buf->result = -EFAULT;
return false;
@@ -263,8 +260,7 @@ static bool filldir(struct dir_context *ctx, const char *name, int namlen,
struct getdents_callback *buf =
container_of(ctx, struct getdents_callback, ctx);
unsigned long d_ino;
- int reclen = ALIGN(offsetof(struct linux_dirent, d_name) + namlen + 2,
- sizeof(long));
+ int reclen = ALIGN(dirent_size(dirent, namlen + 2), sizeof(long));
int prev_reclen;
unsigned int flags = d_type;
@@ -287,23 +283,19 @@ static bool filldir(struct dir_context *ctx, const char *name, int namlen,
return false;
dirent = buf->current_dir;
prev = (void __user *) dirent - prev_reclen;
- if (!user_write_access_begin(prev, reclen + prev_reclen))
- goto efault;
-
- /* This might be 'dirent->d_off', but if so it will get overwritten */
- unsafe_put_user(offset, &prev->d_off, efault_end);
- unsafe_put_user(d_ino, &dirent->d_ino, efault_end);
- unsafe_put_user(reclen, &dirent->d_reclen, efault_end);
- unsafe_put_user(d_type, (char __user *) dirent + reclen - 1, efault_end);
- unsafe_copy_dirent_name(dirent->d_name, name, namlen, efault_end);
- user_write_access_end();
+ scoped_user_write_access_size(prev, reclen + prev_reclen, efault) {
+ /* This might be 'dirent->d_off', but if so it will get overwritten */
+ unsafe_put_user(offset, &prev->d_off, efault);
+ unsafe_put_user(d_ino, &dirent->d_ino, efault);
+ unsafe_put_user(reclen, &dirent->d_reclen, efault);
+ unsafe_put_user(d_type, (char __user *)dirent + reclen - 1, efault);
+ unsafe_copy_dirent_name(dirent->d_name, name, namlen, efault);
+ }
buf->current_dir = (void __user *)dirent + reclen;
buf->prev_reclen = reclen;
ctx->count -= reclen;
return true;
-efault_end:
- user_write_access_end();
efault:
buf->error = -EFAULT;
return false;
@@ -352,8 +344,7 @@ static bool filldir64(struct dir_context *ctx, const char *name, int namlen,
struct linux_dirent64 __user *dirent, *prev;
struct getdents_callback64 *buf =
container_of(ctx, struct getdents_callback64, ctx);
- int reclen = ALIGN(offsetof(struct linux_dirent64, d_name) + namlen + 1,
- sizeof(u64));
+ int reclen = ALIGN(dirent_size(dirent, namlen + 1), sizeof(u64));
int prev_reclen;
unsigned int flags = d_type;
@@ -371,24 +362,20 @@ static bool filldir64(struct dir_context *ctx, const char *name, int namlen,
return false;
dirent = buf->current_dir;
prev = (void __user *)dirent - prev_reclen;
- if (!user_write_access_begin(prev, reclen + prev_reclen))
- goto efault;
-
- /* This might be 'dirent->d_off', but if so it will get overwritten */
- unsafe_put_user(offset, &prev->d_off, efault_end);
- unsafe_put_user(ino, &dirent->d_ino, efault_end);
- unsafe_put_user(reclen, &dirent->d_reclen, efault_end);
- unsafe_put_user(d_type, &dirent->d_type, efault_end);
- unsafe_copy_dirent_name(dirent->d_name, name, namlen, efault_end);
- user_write_access_end();
+ scoped_user_write_access_size(prev, reclen + prev_reclen, efault) {
+ /* This might be 'dirent->d_off', but if so it will get overwritten */
+ unsafe_put_user(offset, &prev->d_off, efault);
+ unsafe_put_user(ino, &dirent->d_ino, efault);
+ unsafe_put_user(reclen, &dirent->d_reclen, efault);
+ unsafe_put_user(d_type, &dirent->d_type, efault);
+ unsafe_copy_dirent_name(dirent->d_name, name, namlen, efault);
+ }
buf->prev_reclen = reclen;
buf->current_dir = (void __user *)dirent + reclen;
ctx->count -= reclen;
return true;
-efault_end:
- user_write_access_end();
efault:
buf->error = -EFAULT;
return false;
@@ -460,18 +447,13 @@ static bool compat_fillonedir(struct dir_context *ctx, const char *name,
}
buf->result++;
dirent = buf->dirent;
- if (!user_write_access_begin(dirent,
- (unsigned long)(dirent->d_name + namlen + 1) -
- (unsigned long)dirent))
- goto efault;
- unsafe_put_user(d_ino, &dirent->d_ino, efault_end);
- unsafe_put_user(offset, &dirent->d_offset, efault_end);
- unsafe_put_user(namlen, &dirent->d_namlen, efault_end);
- unsafe_copy_dirent_name(dirent->d_name, name, namlen, efault_end);
- user_write_access_end();
+ scoped_user_write_access_size(dirent, dirent_size(dirent, namlen + 1), efault) {
+ unsafe_put_user(d_ino, &dirent->d_ino, efault);
+ unsafe_put_user(offset, &dirent->d_offset, efault);
+ unsafe_put_user(namlen, &dirent->d_namlen, efault);
+ unsafe_copy_dirent_name(dirent->d_name, name, namlen, efault);
+ }
return true;
-efault_end:
- user_write_access_end();
efault:
buf->result = -EFAULT;
return false;
@@ -519,8 +501,7 @@ static bool compat_filldir(struct dir_context *ctx, const char *name, int namlen
struct compat_getdents_callback *buf =
container_of(ctx, struct compat_getdents_callback, ctx);
compat_ulong_t d_ino;
- int reclen = ALIGN(offsetof(struct compat_linux_dirent, d_name) +
- namlen + 2, sizeof(compat_long_t));
+ int reclen = ALIGN(dirent_size(dirent, namlen + 2), sizeof(compat_long_t));
int prev_reclen;
unsigned int flags = d_type;
@@ -543,22 +524,18 @@ static bool compat_filldir(struct dir_context *ctx, const char *name, int namlen
return false;
dirent = buf->current_dir;
prev = (void __user *) dirent - prev_reclen;
- if (!user_write_access_begin(prev, reclen + prev_reclen))
- goto efault;
-
- unsafe_put_user(offset, &prev->d_off, efault_end);
- unsafe_put_user(d_ino, &dirent->d_ino, efault_end);
- unsafe_put_user(reclen, &dirent->d_reclen, efault_end);
- unsafe_put_user(d_type, (char __user *) dirent + reclen - 1, efault_end);
- unsafe_copy_dirent_name(dirent->d_name, name, namlen, efault_end);
- user_write_access_end();
+ scoped_user_write_access_size(prev, reclen + prev_reclen, efault) {
+ unsafe_put_user(offset, &prev->d_off, efault);
+ unsafe_put_user(d_ino, &dirent->d_ino, efault);
+ unsafe_put_user(reclen, &dirent->d_reclen, efault);
+ unsafe_put_user(d_type, (char __user *)dirent + reclen - 1, efault);
+ unsafe_copy_dirent_name(dirent->d_name, name, namlen, efault);
+ }
buf->prev_reclen = reclen;
buf->current_dir = (void __user *)dirent + reclen;
ctx->count -= reclen;
return true;
-efault_end:
- user_write_access_end();
efault:
buf->error = -EFAULT;
return false;
diff --git a/fs/select.c b/fs/select.c
index e0244dbe4429..75978b18f48f 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -1004,17 +1004,17 @@ static int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds,
fdcount = do_poll(head, &table, end_time);
poll_freewait(&table);
- if (!user_write_access_begin(ufds, nfds * sizeof(*ufds)))
- goto out_fds;
+ scoped_user_write_access_size(ufds, nfds * sizeof(*ufds), out_fds) {
+ struct pollfd __user *_ufds = ufds;
- for (walk = head; walk; walk = walk->next) {
- struct pollfd *fds = walk->entries;
- unsigned int j;
+ for (walk = head; walk; walk = walk->next) {
+ struct pollfd *fds = walk->entries;
+ unsigned int j;
- for (j = walk->len; j; fds++, ufds++, j--)
- unsafe_put_user(fds->revents, &ufds->revents, Efault);
- }
- user_write_access_end();
+ for (j = walk->len; j; fds++, _ufds++, j--)
+ unsafe_put_user(fds->revents, &_ufds->revents, out_fds);
+ }
+ }
err = fdcount;
out_fds:
@@ -1026,11 +1026,6 @@ out_fds:
}
return err;
-
-Efault:
- user_write_access_end();
- err = -EFAULT;
- goto out_fds;
}
static long do_restart_poll(struct restart_block *restart_block)
@@ -1338,15 +1333,13 @@ static inline int get_compat_sigset_argpack(struct compat_sigset_argpack *to,
struct compat_sigset_argpack __user *from)
{
if (from) {
- if (!user_read_access_begin(from, sizeof(*from)))
- return -EFAULT;
- unsafe_get_user(to->p, &from->p, Efault);
- unsafe_get_user(to->size, &from->size, Efault);
- user_read_access_end();
+ scoped_user_read_access(from, efault) {
+ unsafe_get_user(to->p, &from->p, efault);
+ unsafe_get_user(to->size, &from->size, efault);
+ }
}
return 0;
-Efault:
- user_read_access_end();
+efault:
return -EFAULT;
}
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 1e1580febe4b..4f8e734c4336 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -975,7 +975,9 @@
RUNTIME_CONST(shift, d_hash_shift) \
RUNTIME_CONST(ptr, dentry_hashtable) \
RUNTIME_CONST(ptr, __dentry_cache) \
- RUNTIME_CONST(ptr, __names_cache)
+ RUNTIME_CONST(ptr, __names_cache) \
+ RUNTIME_CONST(ptr, __filp_cache) \
+ RUNTIME_CONST(ptr, __bfilp_cache)
/* Alignment must be consistent with (kunit_suite *) in include/kunit/test.h */
#define KUNIT_TABLE() \
diff --git a/include/linux/backing-dev-defs.h b/include/linux/backing-dev-defs.h
index c88fd4d37d1f..a06b93446d10 100644
--- a/include/linux/backing-dev-defs.h
+++ b/include/linux/backing-dev-defs.h
@@ -237,7 +237,7 @@ static inline void wb_get(struct bdi_writeback *wb)
}
/**
- * wb_put - decrement a wb's refcount
+ * wb_put_many - decrement a wb's refcount
* @wb: bdi_writeback to put
* @nr: number of references to put
*/
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 11857ae13d10..b5e2f3c5e5c0 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -38,6 +38,7 @@ struct blk_flush_queue;
struct kiocb;
struct pr_ops;
struct rq_qos;
+struct hd_geometry;
struct blk_report_zones_args;
struct blk_queue_stats;
struct blk_stat_callback;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 4551edb8d479..547ce27fb741 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -55,8 +55,6 @@ struct bdi_writeback;
struct bio;
struct io_comp_batch;
struct fiemap_extent_info;
-struct hd_geometry;
-struct iovec;
struct kiocb;
struct kobject;
struct pipe_inode_info;
@@ -1920,7 +1918,6 @@ struct dir_context {
*/
#define COPY_FILE_SPLICE (1 << 0)
-struct iov_iter;
struct io_uring_cmd;
struct offset_ctx;
diff --git a/include/linux/fs_parser.h b/include/linux/fs_parser.h
index 5e8a3b546033..98b83708f92b 100644
--- a/include/linux/fs_parser.h
+++ b/include/linux/fs_parser.h
@@ -27,8 +27,8 @@ typedef int fs_param_type(struct p_log *,
* The type of parameter expected.
*/
fs_param_type fs_param_is_bool, fs_param_is_u32, fs_param_is_s32, fs_param_is_u64,
- fs_param_is_enum, fs_param_is_string, fs_param_is_blob, fs_param_is_blockdev,
- fs_param_is_path, fs_param_is_fd, fs_param_is_uid, fs_param_is_gid,
+ fs_param_is_enum, fs_param_is_string, fs_param_is_blockdev,
+ fs_param_is_fd, fs_param_is_uid, fs_param_is_gid,
fs_param_is_file_or_string;
/*
@@ -84,8 +84,6 @@ extern int fs_lookup_param(struct fs_context *fc,
extern int lookup_constant(const struct constant_table tbl[], const char *name, int not_found);
-extern const struct constant_table bool_names[];
-
#ifdef CONFIG_VALIDATE_FS_PARSER
extern bool fs_validate_description(const char *name,
const struct fs_parameter_spec *desc);
@@ -127,9 +125,7 @@ static inline bool fs_validate_description(const char *name,
#define fsparam_enum(NAME, OPT, array) __fsparam(fs_param_is_enum, NAME, OPT, 0, array)
#define fsparam_string(NAME, OPT) \
__fsparam(fs_param_is_string, NAME, OPT, 0, NULL)
-#define fsparam_blob(NAME, OPT) __fsparam(fs_param_is_blob, NAME, OPT, 0, NULL)
#define fsparam_bdev(NAME, OPT) __fsparam(fs_param_is_blockdev, NAME, OPT, 0, NULL)
-#define fsparam_path(NAME, OPT) __fsparam(fs_param_is_path, NAME, OPT, 0, NULL)
#define fsparam_fd(NAME, OPT) __fsparam(fs_param_is_fd, NAME, OPT, 0, NULL)
#define fsparam_file_or_string(NAME, OPT) \
__fsparam(fs_param_is_file_or_string, NAME, OPT, 0, NULL)
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 02bd6ddb6278..f5639d5ac331 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -1283,19 +1283,9 @@ static inline long ksys_lchown(const char __user *filename, uid_t user,
AT_SYMLINK_NOFOLLOW);
}
-int do_sys_ftruncate(unsigned int fd, loff_t length, int small);
-
-static inline long ksys_ftruncate(unsigned int fd, loff_t length)
-{
- return do_sys_ftruncate(fd, length, 1);
-}
-
-int do_sys_truncate(const char __user *pathname, loff_t length);
-
-static inline long ksys_truncate(const char __user *pathname, loff_t length)
-{
- return do_sys_truncate(pathname, length);
-}
+#define FTRUNCATE_LFS (1u << 0) /* allow truncating > 32-bit */
+int ksys_ftruncate(unsigned int fd, loff_t length, unsigned int flags);
+int ksys_truncate(const char __user *pathname, loff_t length);
static inline unsigned int ksys_personality(unsigned int personality)
{
diff --git a/include/trace/events/coredump.h b/include/trace/events/coredump.h
new file mode 100644
index 000000000000..c7b9c53fc498
--- /dev/null
+++ b/include/trace/events/coredump.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2026 Meta Platforms, Inc. and affiliates.
+ * Copyright (c) 2026 Breno Leitao <leitao@debian.org>
+ */
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM coredump
+
+#if !defined(_TRACE_COREDUMP_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_COREDUMP_H
+
+#include <linux/sched.h>
+#include <linux/tracepoint.h>
+
+/**
+ * coredump - called when a coredump starts
+ * @sig: signal number that triggered the coredump
+ *
+ * This tracepoint fires at the beginning of a coredump attempt,
+ * providing a stable interface for monitoring coredump events.
+ */
+TRACE_EVENT(coredump,
+
+ TP_PROTO(int sig),
+
+ TP_ARGS(sig),
+
+ TP_STRUCT__entry(
+ __field(int, sig)
+ __array(char, comm, TASK_COMM_LEN)
+ ),
+
+ TP_fast_assign(
+ __entry->sig = sig;
+ memcpy(__entry->comm, current->comm, TASK_COMM_LEN);
+ ),
+
+ TP_printk("sig=%d comm=%s",
+ __entry->sig, __entry->comm)
+);
+
+#endif /* _TRACE_COREDUMP_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/init/initramfs.c b/init/initramfs.c
index 139baed06589..d29fe0a5ccfc 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -212,7 +212,7 @@ static void __init parse_header(char *s)
hdr_csum = parsed[12];
}
-/* FSM */
+/* Finite-state machine */
static __initdata enum state {
Start,
diff --git a/io_uring/truncate.c b/io_uring/truncate.c
index 487baf23b44e..c88d8bd8d20e 100644
--- a/io_uring/truncate.c
+++ b/io_uring/truncate.c
@@ -41,7 +41,7 @@ int io_ftruncate(struct io_kiocb *req, unsigned int issue_flags)
WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
- ret = do_ftruncate(req->file, ft->len, 1);
+ ret = do_ftruncate(req->file, ft->len, 0);
io_req_set_res(req, ret, 0);
return IOU_COMPLETE;
diff --git a/kernel/acct.c b/kernel/acct.c
index 1e19722c64c3..cbbf79d718cf 100644
--- a/kernel/acct.c
+++ b/kernel/acct.c
@@ -244,7 +244,7 @@ static int acct_on(const char __user *name)
if (!S_ISREG(file_inode(file)->i_mode))
return -EACCES;
- /* Exclude kernel kernel internal filesystems. */
+ /* Exclude kernel internal filesystems. */
if (file_inode(file)->i_sb->s_flags & (SB_NOUSER | SB_KERNMOUNT))
return -EINVAL;
diff --git a/tools/testing/selftests/filesystems/devpts_pts.c b/tools/testing/selftests/filesystems/devpts_pts.c
index 54fea349204e..aa8d5324f2a6 100644
--- a/tools/testing/selftests/filesystems/devpts_pts.c
+++ b/tools/testing/selftests/filesystems/devpts_pts.c
@@ -119,9 +119,7 @@ static int do_tiocgptpeer(char *ptmx, char *expected_procfd_contents)
goto do_cleanup;
}
-#ifdef TIOCGPTPEER
slave = ioctl(master, TIOCGPTPEER, O_RDWR | O_NOCTTY | O_CLOEXEC);
-#endif
if (slave < 0) {
if (errno == EINVAL) {
fprintf(stderr, "TIOCGPTPEER is not supported. "