diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-04-14 00:20:11 +0300 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-04-14 00:20:11 +0300 |
| commit | ef3da345ccb1fd70e2288b821301698483c6c35a (patch) | |
| tree | 2d834bc8ca248beb78d51542eb1b79b57b193636 | |
| parent | 07c3ef58223e2c75ea209d8c416b976ec30d9413 (diff) | |
| parent | 97b67e64affb0e709eeecc50f6a9222fc20bd14b (diff) | |
| download | linux-ef3da345ccb1fd70e2288b821301698483c6c35a.tar.xz | |
Merge tag 'vfs-7.1-rc1.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
Pull misc vfs updates from Christian Brauner:
"Features:
- coredump: add tracepoint for coredump events
- fs: hide file and bfile caches behind runtime const machinery
Fixes:
- fix architecture-specific compat_ftruncate64 implementations
- dcache: Limit the minimal number of bucket to two
- fs/omfs: reject s_sys_blocksize smaller than OMFS_DIR_START
- fs/mbcache: cancel shrink work before destroying the cache
- dcache: permit dynamic_dname()s up to NAME_MAX
Cleanups:
- remove or unexport unused fs_context infrastructure
- trivial ->setattr cleanups
- selftests/filesystems: Assume that TIOCGPTPEER is defined
- writeback: fix kernel-doc function name mismatch for wb_put_many()
- autofs: replace manual symlink buffer allocation in autofs_dir_symlink
- init/initramfs.c: trivial fix: FSM -> Finite-state machine
- fs: remove stale and duplicate forward declarations
- readdir: Introduce dirent_size()
- fs: Replace user_access_{begin/end} by scoped user access
- kernel: acct: fix duplicate word in comment
- fs: write a better comment in step_into() concerning .mnt assignment
- fs: attr: fix comment formatting and spelling issues"
* tag 'vfs-7.1-rc1.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: (28 commits)
dcache: permit dynamic_dname()s up to NAME_MAX
fs: attr: fix comment formatting and spelling issues
fs: hide file and bfile caches behind runtime const machinery
fs: write a better comment in step_into() concerning .mnt assignment
proc: rename proc_notify_change to proc_setattr
proc: rename proc_setattr to proc_nochmod_setattr
affs: rename affs_notify_change to affs_setattr
adfs: rename adfs_notify_change to adfs_setattr
hfs: update comments on hfs_inode_setattr
kernel: acct: fix duplicate word in comment
fs: Replace user_access_{begin/end} by scoped user access
readdir: Introduce dirent_size()
coredump: add tracepoint for coredump events
fs: remove do_sys_truncate
fs: pass on FTRUNCATE_* flags to do_truncate
fs: fix archiecture-specific compat_ftruncate64
fs: remove stale and duplicate forward declarations
init/initramfs.c: trivial fix: FSM -> Finite-state machine
autofs: replace manual symlink buffer allocation in autofs_dir_symlink
fs/mbcache: cancel shrink work before destroying the cache
...
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. " |
