Linux 5.15.52
Greg Kroah-Hartman
maintainerI'm announcing the release of the 5.15.52 kernel.
All users of the 5.15 kernel series must upgrade.
The updated 5.15.y git tree can be found at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git linux-5.15.y
and can be browsed at the normal kernel.org git web browser:
https://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git;a=summary
thanks,
greg k-h
------------
Documentation/filesystems/idmappings.rst | 72 -------- Makefile | 2 arch/powerpc/include/asm/ftrace.h | 4 arch/powerpc/kernel/trace/ftrace.c | 15 + arch/powerpc/mm/mem.c | 2 arch/x86/kernel/kvm.c | 2 drivers/md/bcache/btree.c | 1 drivers/md/bcache/writeback.c | 1 drivers/net/ethernet/mscc/ocelot.c | 8 drivers/net/wireless/realtek/rtw88/rtw8821c.c | 14 + fs/attr.c | 26 ++ fs/cachefiles/bind.c | 2 fs/ecryptfs/main.c | 2 fs/io_uring.c | 28 +-- fs/ksmbd/smbacl.c | 19 -- fs/ksmbd/smbacl.h | 5 fs/namespace.c | 53 ++++- fs/nfsd/export.c | 2 fs/open.c | 8 fs/overlayfs/super.c | 2 fs/posix_acl.c | 27 ++- fs/proc_namespace.c | 2 fs/xattr.c | 6 fs/xfs/libxfs/xfs_attr.c | 17 - fs/xfs/xfs_aops.c | 15 + fs/xfs/xfs_buf_item_recover.c | 2 fs/xfs/xfs_extfree_item.c | 6 fs/xfs/xfs_inode.c | 8 fs/xfs/xfs_linux.h | 1 fs/xfs/xfs_log_cil.c | 6 fs/xfs/xfs_super.c | 21 +- fs/xfs/xfs_symlink.c | 4 include/linux/fs.h | 141 ++++----------- include/linux/mnt_idmapping.h | 234 ++++++++++++++++++++++++++ include/linux/posix_acl_xattr.h | 4 kernel/time/tick-sched.c | 1 security/commoncap.c | 15 + 37 files changed, 490 insertions(+), 288 deletions(-)
Brian Foster (1):
xfs: punch out data fork delalloc blocks on COW writeback failure
Christian Brauner (12):
fs: add is_idmapped_mnt() helper
fs: move mapping helpers
fs: tweak fsuidgid_has_mapping()
fs: account for filesystem mappings
docs: update mapping documentation
fs: use low-level mapping helpers
fs: remove unused low-level mapping helpers
fs: port higher-level mapping helpers
fs: add i_user_ns() helper
fs: support mapped mounts of mapped filesystems
fs: fix acl translation
fs: account for group membership
Coly Li (1):
bcache: memset on stack variables in bch_btree_check() and bch_sectors_dirty_init()
Darrick J. Wong (3):
xfs: remove all COW fork extents when remounting readonly
xfs: prevent UAF in xfs_log_item_in_current_chkpt
xfs: only bother with sync_filesystem during readonly remount
Dave Chinner (1):
xfs: check sb_meta_uuid for dabuf buffer recovery
Greg Kroah-Hartman (2):
x86, kvm: use proper ASM macros for kvm_vcpu_is_preempted Linux 5.15.52
Guo-Feng Fan (1):
rtw88: 8821c: support RFE type4 wifi NIC
Masahiro Yamada (1):
tick/nohz: unexport __init-annotated tick_nohz_full_setup()
Naveen N. Rao (1):
powerpc/ftrace: Remove ftrace init tramp once kernel init is complete
Pavel Begunkov (1):
io_uring: fix not locked access to fixed buf table
Ping-Ke Shih (1):
rtw88: rtw8821c: enable rfe 6 devices
Rustam Kovhaev (1):
xfs: use kmem_cache_free() for kmem_cache objects
Vladimir Oltean (1):
net: mscc: ocelot: allow unregistered IP multicast flooding to CPU
Yang Xu (1):
xfs: Fix the free logic of state in xfs_attr_node_hasname
Greg Kroah-Hartman
maintainerDocumentation/filesystems/idmappings.rst +0 -72
@@ -952,75 +952,3 @@ The raw userspace id that is put on disk is ``u1000`` so when the user takes their home directory back to their home computer where they are assigned ``u1000`` using the initial idmapping and mount the filesystem with the initial idmapping they will see all those files owned by ``u1000``. - -Shortcircuting --------------- - -Currently, the implementation of idmapped mounts enforces that the filesystem -is mounted with the initial idmapping. The reason is simply that none of the -filesystems that we targeted were mountable with a non-initial idmapping. But -that might change soon enough. As we've seen above, thanks to the properties of -idmappings the translation works for both filesystems mounted with the initial -idmapping and filesystem with non-initial idmappings. - -Based on this current restriction to filesystem mounted with the initial -idmapping two noticeable shortcuts have been taken: - -1. We always stash a reference to the initial user namespace in ``struct - vfsmount``. Idmapped mounts are thus mounts that have a non-initial user - namespace attached to them. - - In order to support idmapped mounts this needs to be changed. Instead of - stashing the initial user namespace the user namespace the filesystem was - mounted with must be stashed. An idmapped mount is then any mount that has - a different user namespace attached then the filesystem was mounted with. - This has no user-visible consequences. - -2. The translation algorithms in ``mapped_fs*id()`` and ``i_*id_into_mnt()`` - are simplified. - - Let's consider ``mapped_fs*id()`` first. This function translates the - caller's kernel id into a kernel id in the filesystem's idmapping via - a mount's idmapping. The full algorithm is:: - - mapped_fsuid(kid): - /* Map the kernel id up into a userspace id in the mount's idmapping. */ - from_kuid(mount-idmapping, kid) = uid - - /* Map the userspace id down into a kernel id in the filesystem's idmapping. */ - make_kuid(filesystem-idmapping, uid) = kuid - - We know that the filesystem is always mounted with the initial idmapping as - we enforce this in ``mount_setattr()``. So this can be shortened to:: - - mapped_fsuid(kid): - /* Map the kernel id up into a userspace id in the mount's idmapping. */ - from_kuid(mount-idmapping, kid) = uid - - /* Map the userspace id down into a kernel id in the filesystem's idmapping. */ - KUIDT_INIT(uid) = kuid - - Similarly, for ``i_*id_into_mnt()`` which translated the filesystem's kernel - id into a mount's kernel id:: - - i_uid_into_mnt(kid): - /* Map the kernel id up into a userspace id in the filesystem's idmapping. */ - from_kuid(filesystem-idmapping, kid) = uid - - /* Map the userspace id down into a kernel id in the mounts's idmapping. */ - make_kuid(mount-idmapping, uid) = kuid - - Again, we know that the filesystem is always mounted with the initial - idmapping as we enforce this in ``mount_setattr()``. So this can be - shortened to:: - - i_uid_into_mnt(kid): - /* Map the kernel id up into a userspace id in the filesystem's idmapping. */ - __kuid_val(kid) = uid - - /* Map the userspace id down into a kernel id in the mounts's idmapping. */ - make_kuid(mount-idmapping, uid) = kuid - -Handling filesystems mounted with non-initial idmappings requires that the -translation functions be converted to their full form. They can still be -shortcircuited on non-idmapped mounts. This has no user-visible consequences.
Makefile +1 -1
@@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 VERSION = 5 PATCHLEVEL = 15 -SUBLEVEL = 51 +SUBLEVEL = 52 EXTRAVERSION = NAME = Trick or Treat
arch/powerpc/include/asm/ftrace.h +3 -1
@@ -96,7 +96,7 @@ static inline bool arch_syscall_match_sym_name(const char *sym, const char *name#endif /* PPC64_ELF_ABI_v1 */ #endif /* CONFIG_FTRACE_SYSCALLS */ -#ifdef CONFIG_PPC64 +#if defined(CONFIG_PPC64 ) && defined(CONFIG_FUNCTION_TRACER )#include <asm/paca.h> static inline void this_cpu_disable_ftrace (void )
@@ -120,11 +120,13 @@ static inline u8 this_cpu_get_ftrace_enabled(void)return get_paca ()->ftrace_enabled; } +void ftrace_free_init_tramp (void );#else /* CONFIG_PPC64 */ static inline void this_cpu_disable_ftrace (void ) { }static inline void this_cpu_enable_ftrace (void ) { }static inline void this_cpu_set_ftrace_enabled (u8 ftrace_enabled) { }static inline u8 this_cpu_get_ftrace_enabled (void ) {return 1 ; } +static inline void ftrace_free_init_tramp (void ) { }#endif /* CONFIG_PPC64 */ #endif /* !__ASSEMBLY__ */
arch/powerpc/kernel/trace/ftrace.c +12 -3
@@ -336,9 +336,7 @@ static int setup_mcount_compiler_tramp(unsigned long tramp)/* Is this a known long jump tramp? */ for (i =0 ; i <NUM_FTRACE_TRAMPS ; i++) -if (!ftrace_tramps[i]) -break ; -else if (ftrace_tramps[i] == tramp) +if (ftrace_tramps[i] == tramp)return 0 ;/* Is this a known plt tramp? */
@@ -881,6 +879,17 @@ void arch_ftrace_update_code(int command)extern unsigned int ftrace_tramp_text[], ftrace_tramp_init[]; +void ftrace_free_init_tramp (void ) +{ +int i; + +for (i =0 ; i <NUM_FTRACE_TRAMPS && ftrace_tramps[i]; i++) +if (ftrace_tramps[i] == (unsigned long )ftrace_tramp_init) { + ftrace_tramps[i] =0 ; +return ; + } +} +int __init ftrace_dyn_arch_init (void ) {int i;
arch/powerpc/mm/mem.c +2 -0
@@ -22,6 +22,7 @@#include <asm/kasan.h> #include <asm/svm.h> #include <asm/mmzone.h> +#include <asm/ftrace.h> #include <mm/mmu_decl.h>
@@ -314,6 +315,7 @@ void free_initmem(void)mark_initmem_nx (); init_mem_is_free = true;free_initmem_default (POISON_FREE_INITMEM ); +ftrace_free_init_tramp (); }/*
arch/x86/kernel/kvm.c +1 -1
@@ -948,7 +948,7 @@ asm("movq __per_cpu_offset(,%rdi,8), %rax;" "cmpb $0, " __stringify(KVM_STEAL_TIME_preempted) "+steal_time(%rax);""setne %al;" -"ret;" +ASM_RET ".size __raw_callee_save___kvm_vcpu_is_preempted, .-__raw_callee_save___kvm_vcpu_is_preempted;" ".popsection");
drivers/md/bcache/btree.c +1 -0
@@ -2017,6 +2017,7 @@ int bch_btree_check(struct cache_set *c)if (c->root->level ==0 )return 0 ; +memset (&check_state,0 ,sizeof (struct btree_check_state )); check_state.c = c; check_state.total_threads =bch_btree_chkthread_nr (); check_state.key_idx =0 ;
drivers/md/bcache/writeback.c +1 -0
@@ -947,6 +947,7 @@ void bch_sectors_dirty_init(struct bcache_device *d)return ; } +memset (&state,0 ,sizeof (struct bch_dirty_init_state )); state.c = c; state.d = d; state.total_threads =bch_btre_dirty_init_thread_nr ();
drivers/net/ethernet/mscc/ocelot.c +6 -2
@@ -2206,11 +2206,15 @@ int ocelot_init(struct ocelot *ocelot)ocelot_rmw_rix (ocelot,ANA_PGID_PGID_PGID (BIT (ocelot->num_phys_ports)),ANA_PGID_PGID_PGID (BIT (ocelot->num_phys_ports)),ANA_PGID_PGID ,PGID_MC ); +ocelot_rmw_rix (ocelot,ANA_PGID_PGID_PGID (BIT (ocelot->num_phys_ports)), +ANA_PGID_PGID_PGID (BIT (ocelot->num_phys_ports)), +ANA_PGID_PGID ,PGID_MCIPV4 ); +ocelot_rmw_rix (ocelot,ANA_PGID_PGID_PGID (BIT (ocelot->num_phys_ports)), +ANA_PGID_PGID_PGID (BIT (ocelot->num_phys_ports)), +ANA_PGID_PGID ,PGID_MCIPV6 );ocelot_rmw_rix (ocelot,ANA_PGID_PGID_PGID (BIT (ocelot->num_phys_ports)),ANA_PGID_PGID_PGID (BIT (ocelot->num_phys_ports)),ANA_PGID_PGID ,PGID_BC ); -ocelot_write_rix (ocelot,0 ,ANA_PGID_PGID ,PGID_MCIPV4 ); -ocelot_write_rix (ocelot,0 ,ANA_PGID_PGID ,PGID_MCIPV6 );/* Allow manual injection via DEVCPU_QS registers, and byte swap these * registers endianness.
drivers/net/wireless/realtek/rtw88/rtw8821c.c +13 -1
@@ -304,7 +304,8 @@ static void rtw8821c_set_channel_rf(struct rtw_dev *rtwdev, u8 channel, u8 bw)if (channel <=14 ) {if (rtwdev->efuse.rfe_option ==0 )rtw8821c_switch_rf_set (rtwdev,SWITCH_TO_WLG ); -else if (rtwdev->efuse.rfe_option ==2 ) +else if (rtwdev->efuse.rfe_option ==2 || + rtwdev->efuse.rfe_option ==4 )rtw8821c_switch_rf_set (rtwdev,SWITCH_TO_BTG );rtw_write_rf (rtwdev,RF_PATH_A ,RF_LUTDBG ,BIT (6 ),0x1 );rtw_write_rf (rtwdev,RF_PATH_A ,0x64 ,0xf ,0xf );
@@ -777,6 +778,15 @@ static void rtw8821c_coex_cfg_ant_switch(struct rtw_dev *rtwdev, u8 ctrl_type,if (switch_status == coex_dm->cur_switch_status)return ; +if (coex_rfe->wlg_at_btg) { + ctrl_type =COEX_SWITCH_CTRL_BY_BBSW ; + +if (coex_rfe->ant_switch_polarity) + pos_type =COEX_SWITCH_TO_WLA ; +else + pos_type =COEX_SWITCH_TO_WLG_BT ; + } + coex_dm->cur_switch_status = switch_status; if (coex_rfe->ant_switch_diversity &&
@@ -1502,6 +1512,8 @@ static const struct rtw_intf_phy_para_table phy_para_table_8821c = {static const struct rtw_rfe_def rtw8821c_rfe_defs[] = { [0] = RTW_DEF_RFE(8821c, 0, 0), [2] = RTW_DEF_RFE_EXT(8821c, 0, 0, 2), + [4] = RTW_DEF_RFE_EXT(8821c, 0, 0, 2), + [6] = RTW_DEF_RFE(8821c, 0, 0), };static struct rtw_hw_reg rtw8821c_dig[] = {
fs/attr.c +20 -6
@@ -61,9 +61,15 @@ static bool chgrp_ok(struct user_namespace *mnt_userns, const struct inode *inode, kgid_t gid) {kgid_t kgid =i_gid_into_mnt (mnt_userns, inode); -if (uid_eq (current_fsuid (),i_uid_into_mnt (mnt_userns, inode)) && - (in_group_p (gid) ||gid_eq (gid, inode->i_gid))) -return true; +if (uid_eq (current_fsuid (),i_uid_into_mnt (mnt_userns, inode))) { +kgid_t mapped_gid; + +if (gid_eq (gid, inode->i_gid)) +return true; + mapped_gid =mapped_kgid_fs (mnt_userns,i_user_ns (inode), gid); +if (in_group_p (mapped_gid)) +return true; + }if (capable_wrt_inode_uidgid (mnt_userns, inode,CAP_CHOWN ))return true; if (gid_eq(kgid, INVALID_GID) &&
@@ -123,12 +129,20 @@ int setattr_prepare(struct user_namespace *mnt_userns, struct dentry *dentry,/* Make sure a caller can chmod. */ if (ia_valid &ATTR_MODE ) { +kgid_t mapped_gid; +if (!inode_owner_or_capable (mnt_userns, inode))return -EPERM ; + +if (ia_valid &ATTR_GID ) + mapped_gid =mapped_kgid_fs (mnt_userns, +i_user_ns (inode), attr->ia_gid); +else + mapped_gid =i_gid_into_mnt (mnt_userns, inode); +/* Also check the setgid bit! */ -if (!in_group_p ((ia_valid &ATTR_GID ) ? attr->ia_gid : -i_gid_into_mnt (mnt_userns, inode)) && - !capable_wrt_inode_uidgid (mnt_userns, inode,CAP_FSETID )) +if (!in_group_p (mapped_gid) && + !capable_wrt_inode_uidgid (mnt_userns, inode,CAP_FSETID )) attr->ia_mode &= ~S_ISGID ; }
fs/cachefiles/bind.c +1 -1
@@ -117,7 +117,7 @@ static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache) root = path.dentry; ret = -EINVAL ; -if (mnt_user_ns (path.mnt) != &init_user_ns) { +if (is_idmapped_mnt (path.mnt)) {pr_warn ("File cache on idmapped mounts not supported" ); goto error_unsupported; }
fs/ecryptfs/main.c +1 -1
@@ -537,7 +537,7 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags goto out_free; } -if (mnt_user_ns (path.mnt) != &init_user_ns) { +if (is_idmapped_mnt (path.mnt)) { rc = -EINVAL ;printk (KERN_ERR "Mounting on idmapped mounts currently disallowed\n" ); goto out_free;
fs/io_uring.c +14 -14
@@ -2932,15 +2932,24 @@ static int io_prep_rw(struct io_kiocb *req, const struct io_uring_sqe *sqe, kiocb->ki_complete = io_complete_rw; } +/* used for fixed read/write too - just read unconditionally */ + req->buf_index =READ_ONCE (sqe->buf_index); + req->imu =NULL ; +if (req->opcode ==IORING_OP_READ_FIXED || req->opcode ==IORING_OP_WRITE_FIXED ) { - req->imu =NULL ; +struct io_ring_ctx *ctx = req->ctx; +u16 index; + +if (unlikely (req->buf_index >= ctx->nr_user_bufs)) +return -EFAULT ; + index =array_index_nospec (req->buf_index, ctx->nr_user_bufs); + req->imu = ctx->user_bufs[index];io_req_set_rsrc_node (req); } req->rw.addr =READ_ONCE (sqe->addr); req->rw.len =READ_ONCE (sqe->len); - req->buf_index =READ_ONCE (sqe->buf_index);return 0 ; }
@@ -3066,18 +3075,9 @@ static int __io_import_fixed(struct io_kiocb *req, int rw, struct iov_iter *iterstatic int io_import_fixed (struct io_kiocb *req,int rw,struct iov_iter *iter) { -struct io_ring_ctx *ctx = req->ctx; -struct io_mapped_ubuf *imu = req->imu; -u16 index, buf_index = req->buf_index; - -if (likely (!imu)) { -if (unlikely (buf_index >= ctx->nr_user_bufs)) -return -EFAULT ; - index =array_index_nospec (buf_index, ctx->nr_user_bufs); - imu =READ_ONCE (ctx->user_bufs[index]); - req->imu = imu; - } -return __io_import_fixed (req, rw, iter, imu); +if (WARN_ON_ONCE (!req->imu)) +return -EFAULT ; +return __io_import_fixed (req, rw, iter, req->imu); }static void io_ring_submit_unlock (struct io_ring_ctx *ctx,bool needs_lock)
fs/ksmbd/smbacl.c +3 -16
@@ -9,6 +9,7 @@#include <linux/fs.h> #include <linux/slab.h> #include <linux/string.h> +#include <linux/mnt_idmapping.h> #include "smbacl.h" #include "smb_common.h"
@@ -274,14 +275,7 @@ static int sid_to_id(struct user_namespace *user_ns,uid_t id; id =le32_to_cpu (psid->sub_auth[psid->num_subauth -1 ]); -/* -* Translate raw sid into kuid in the server's user -* namespace. -*/ - uid =make_kuid (&init_user_ns, id); - -/* If this is an idmapped mount, apply the idmapping. */ - uid =kuid_from_mnt (user_ns, uid); + uid =mapped_kuid_user (user_ns, &init_user_ns,KUIDT_INIT (id));if (uid_valid (uid)) { fattr->cf_uid = uid; rc =0 ;
@@ -291,14 +285,7 @@ static int sid_to_id(struct user_namespace *user_ns,gid_t id; id =le32_to_cpu (psid->sub_auth[psid->num_subauth -1 ]); -/* -* Translate raw sid into kgid in the server's user -* namespace. -*/ - gid =make_kgid (&init_user_ns, id); - -/* If this is an idmapped mount, apply the idmapping. */ - gid =kgid_from_mnt (user_ns, gid); + gid =mapped_kgid_user (user_ns, &init_user_ns,KGIDT_INIT (id));if (gid_valid (gid)) { fattr->cf_gid = gid; rc =0 ;
fs/ksmbd/smbacl.h +3 -2
@@ -11,6 +11,7 @@#include <linux/fs.h> #include <linux/namei.h> #include <linux/posix_acl.h> +#include <linux/mnt_idmapping.h> #include "mgmt/tree_connect.h"
@@ -216,7 +217,7 @@ static inline uid_t posix_acl_uid_translate(struct user_namespace *mnt_userns,kuid_t kuid;/* If this is an idmapped mount, apply the idmapping. */ - kuid =kuid_into_mnt (mnt_userns, pace->e_uid); + kuid =mapped_kuid_fs (mnt_userns, &init_user_ns, pace->e_uid);/* Translate the kuid into a userspace id ksmbd would see. */ return from_kuid (&init_user_ns, kuid);
@@ -228,7 +229,7 @@ static inline gid_t posix_acl_gid_translate(struct user_namespace *mnt_userns,kgid_t kgid;/* If this is an idmapped mount, apply the idmapping. */ - kgid =kgid_into_mnt (mnt_userns, pace->e_gid); + kgid =mapped_kgid_fs (mnt_userns, &init_user_ns, pace->e_gid);/* Translate the kgid into a userspace id ksmbd would see. */ return from_kgid (&init_user_ns, kgid);
fs/namespace.c +39 -14
126 lines not on this page · raw message
fs/nfsd/export.c +1 -1
@@ -427,7 +427,7 @@ static int check_export(struct path *path, int *flags, unsigned char *uuid)return -EINVAL ; } -if (mnt_user_ns (path->mnt) != &init_user_ns) { +if (is_idmapped_mnt (path->mnt)) {dprintk ("exp_export: export of idmapped mounts not yet supported.\n" );return -EINVAL ; }
fs/open.c +5 -3
@@ -32,6 +32,7 @@#include <linux/ima.h> #include <linux/dnotify.h> #include <linux/compat.h> +#include <linux/mnt_idmapping.h> #include "internal.h"
@@ -640,7 +641,7 @@ SYSCALL_DEFINE2(chmod, const char __user *, filename, umode_t, mode)int chown_common (const struct path *path,uid_t user,gid_t group) { -struct user_namespace *mnt_userns; +struct user_namespace *mnt_userns, *fs_userns;struct inode *inode = path->dentry->d_inode;struct inode *delegated_inode =NULL ;int error;
@@ -652,8 +653,9 @@ int chown_common(const struct path *path, uid_t user, gid_t group) gid =make_kgid (current_user_ns (), group); mnt_userns =mnt_user_ns (path->mnt); - uid =kuid_from_mnt (mnt_userns, uid); - gid =kgid_from_mnt (mnt_userns, gid); + fs_userns =i_user_ns (inode); + uid =mapped_kuid_user (mnt_userns, fs_userns, uid); + gid =mapped_kgid_user (mnt_userns, fs_userns, gid); retry_deleg: newattrs.ia_valid =ATTR_CTIME ;
fs/overlayfs/super.c +1 -1
@@ -873,7 +873,7 @@ static int ovl_mount_dir_noesc(const char *name, struct path *path)pr_err ("filesystem on '%s' not supported\n" , name); goto out_put; } -if (mnt_user_ns (path->mnt) != &init_user_ns) { +if (is_idmapped_mnt (path->mnt)) {pr_err ("idmapped layers are currently not supported\n" ); goto out_put; }
fs/posix_acl.c +21 -6
@@ -23,6 +23,7 @@#include <linux/export.h> #include <linux/user_namespace.h> #include <linux/namei.h> +#include <linux/mnt_idmapping.h> static struct posix_acl **acl_by_type (struct inode *inode,int type) {
@@ -375,7 +376,9 @@ posix_acl_permission(struct user_namespace *mnt_userns, struct inode *inode, goto check_perm;break ;case ACL_USER : - uid =kuid_into_mnt (mnt_userns, pa->e_uid); + uid =mapped_kuid_fs (mnt_userns, +i_user_ns (inode), + pa->e_uid);if (uid_eq (uid,current_fsuid ())) goto mask;break ;
@@ -388,7 +391,9 @@ posix_acl_permission(struct user_namespace *mnt_userns, struct inode *inode, }break ;case ACL_GROUP : - gid =kgid_into_mnt (mnt_userns, pa->e_gid); + gid =mapped_kgid_fs (mnt_userns, +i_user_ns (inode), + pa->e_gid);if (in_group_p (gid)) { found =1 ;if ((pa->e_perm & want) == want)
@@ -735,17 +740,17 @@ static void posix_acl_fix_xattr_userns(case ACL_USER : uid =make_kuid (from,le32_to_cpu (entry->e_id));if (from_user) - uid =kuid_from_mnt (mnt_userns, uid); + uid =mapped_kuid_user (mnt_userns, &init_user_ns, uid);else - uid =kuid_into_mnt (mnt_userns, uid); + uid =mapped_kuid_fs (mnt_userns, &init_user_ns, uid); entry->e_id =cpu_to_le32 (from_kuid (to, uid));break ;case ACL_GROUP : gid =make_kgid (from,le32_to_cpu (entry->e_id));if (from_user) - gid =kgid_from_mnt (mnt_userns, gid); + gid =mapped_kgid_user (mnt_userns, &init_user_ns, gid);else - gid =kgid_into_mnt (mnt_userns, gid); + gid =mapped_kgid_fs (mnt_userns, &init_user_ns, gid); entry->e_id =cpu_to_le32 (from_kgid (to, gid));break ;default :
@@ -755,9 +760,14 @@ static void posix_acl_fix_xattr_userns( }void posix_acl_fix_xattr_from_user (struct user_namespace *mnt_userns, +struct inode *inode,void *value,size_t size) {struct user_namespace *user_ns =current_user_ns (); + +/* Leave ids untouched on non-idmapped mounts. */ +if (no_idmapping (mnt_userns,i_user_ns (inode))) + mnt_userns = &init_user_ns;if ((user_ns == &init_user_ns) && (mnt_userns == &init_user_ns))return ; posix_acl_fix_xattr_userns(&init_user_ns, user_ns, mnt_userns, value,
@@ -765,9 +775,14 @@ void posix_acl_fix_xattr_from_user(struct user_namespace *mnt_userns, }void posix_acl_fix_xattr_to_user (struct user_namespace *mnt_userns, +struct inode *inode,void *value,size_t size) {struct user_namespace *user_ns =current_user_ns (); + +/* Leave ids untouched on non-idmapped mounts. */ +if (no_idmapping (mnt_userns,i_user_ns (inode))) + mnt_userns = &init_user_ns;if ((user_ns == &init_user_ns) && (mnt_userns == &init_user_ns))return ; posix_acl_fix_xattr_userns(user_ns, &init_user_ns, mnt_userns, value,
fs/proc_namespace.c +1 -1
@@ -80,7 +80,7 @@ static void show_mnt_opts(struct seq_file *m, struct vfsmount *mnt)seq_puts (m, fs_infop->str); } -if (mnt_user_ns (mnt) != &init_user_ns) +if (is_idmapped_mnt (mnt))seq_puts (m,",idmapped" ); }
fs/xattr.c +4 -2
@@ -569,7 +569,8 @@ setxattr(struct user_namespace *mnt_userns, struct dentry *d, }if ((strcmp (kname,XATTR_NAME_POSIX_ACL_ACCESS ) ==0 ) || (strcmp (kname,XATTR_NAME_POSIX_ACL_DEFAULT ) ==0 )) -posix_acl_fix_xattr_from_user (mnt_userns, kvalue, size); +posix_acl_fix_xattr_from_user (mnt_userns,d_inode (d), + kvalue, size); } error =vfs_setxattr (mnt_userns, d, kname, kvalue, size, flags);
@@ -667,7 +668,8 @@ getxattr(struct user_namespace *mnt_userns, struct dentry *d,if (error >0 ) {if ((strcmp (kname,XATTR_NAME_POSIX_ACL_ACCESS ) ==0 ) || (strcmp (kname,XATTR_NAME_POSIX_ACL_DEFAULT ) ==0 )) -posix_acl_fix_xattr_to_user (mnt_userns, kvalue, error); +posix_acl_fix_xattr_to_user (mnt_userns,d_inode (d), + kvalue, error);if (size &©_to_user (value, kvalue, error)) error = -EFAULT ; }else if (error == -ERANGE && size >=XATTR_SIZE_MAX ) {
fs/xfs/libxfs/xfs_attr.c +7 -10
@@ -1077,21 +1077,18 @@ xfs_attr_node_hasname( state =xfs_da_state_alloc (args);if (statep !=NULL ) - *statep =NULL ; + *statep = state;/* * Search to see if name exists, and get back a pointer to it. */ error =xfs_da3_node_lookup_int (state, &retval); -if (error) { -xfs_da_state_free (state); -return error; - } +if (error) + retval = error; -if (statep !=NULL ) - *statep = state; -else +if (!statep)xfs_da_state_free (state); +return retval; }
@@ -1112,7 +1109,7 @@ xfs_attr_node_addname_find_attr(*/ retval =xfs_attr_node_hasname (args, &dac->da_state);if (retval != -ENOATTR && retval != -EEXIST ) -return retval; + goto error;if (retval == -ENOATTR && (args->attr_flags &XATTR_REPLACE )) goto error;
@@ -1337,7 +1334,7 @@ int xfs_attr_node_removename_setup( error =xfs_attr_node_hasname (args, state);if (error != -EEXIST ) -return error; + goto out; error =0 ;ASSERT ((*state)->path.blk[(*state)->path.active -1 ].bp !=NULL );
fs/xfs/xfs_aops.c +12 -3
@@ -82,6 +82,7 @@ xfs_end_ioend( struct iomap_ioend *ioend) {struct xfs_inode *ip =XFS_I (ioend->io_inode); +struct xfs_mount *mp = ip->i_mount;xfs_off_t offset = ioend->io_offset;size_t size = ioend->io_size;unsigned int nofs_flag;
@@ -97,18 +98,26 @@ xfs_end_ioend(/* * Just clean up the in-memory structures if the fs has been shut down. */ -if (xfs_is_shutdown (ip->i_mount)) { +if (xfs_is_shutdown (mp)) { error = -EIO ; goto done; }/* -* Clean up any COW blocks on an I/O error. +* Clean up all COW blocks and underlying data fork delalloc blocks on +* I/O error. The delalloc punch is required because this ioend was +* mapped to blocks in the COW fork and the associated pages are no +* longer dirty. If we don't remove delalloc blocks here, they become +* stale and can corrupt free space accounting on unmount. */ error =blk_status_to_errno (ioend->io_bio->bi_status);if (unlikely (error)) { -if (ioend->io_flags &IOMAP_F_SHARED ) +if (ioend->io_flags &IOMAP_F_SHARED ) {xfs_reflink_cancel_cow_range (ip, offset, size, true); +xfs_bmap_punch_delalloc_range (ip, +XFS_B_TO_FSBT (mp, offset), +XFS_B_TO_FSB (mp, size)); + } goto done; }
fs/xfs/xfs_buf_item_recover.c +1 -1
@@ -816,7 +816,7 @@ xlog_recover_get_buf_lsn( }if (lsn != (xfs_lsn_t)-1 ) { -if (!uuid_equal (&mp->m_sb.sb_uuid, uuid)) +if (!uuid_equal (&mp->m_sb.sb_meta_uuid, uuid)) goto recover_immediately;return lsn; }
fs/xfs/xfs_extfree_item.c +3 -3
@@ -482,7 +482,7 @@ xfs_extent_free_finish_item( free->xefi_startblock, free->xefi_blockcount, &free->xefi_oinfo, free->xefi_skip_discard); -kmem_free (free); +kmem_cache_free (xfs_bmap_free_item_zone, free);return error; }
@@ -502,7 +502,7 @@ xfs_extent_free_cancel_item(struct xfs_extent_free_item *free; free = container_of(item, struct xfs_extent_free_item, xefi_list); -kmem_free (free); +kmem_cache_free (xfs_bmap_free_item_zone, free); }const struct xfs_defer_op_type xfs_extent_free_defer_type = {
@@ -564,7 +564,7 @@ xfs_agfl_free_finish_item( extp->ext_len = free->xefi_blockcount; efdp->efd_next_extent++; -kmem_free (free); +kmem_cache_free (xfs_bmap_free_item_zone, free);return error; }
fs/xfs/xfs_inode.c +4 -4
@@ -994,8 +994,8 @@ xfs_create(/* * Make sure that we have allocated dquot(s) on disk. */ - error =xfs_qm_vop_dqalloc (dp,mapped_fsuid (mnt_userns), -mapped_fsgid (mnt_userns), prid, + error =xfs_qm_vop_dqalloc (dp,mapped_fsuid (mnt_userns, &init_user_ns), +mapped_fsgid (mnt_userns, &init_user_ns), prid,XFS_QMOPT_QUOTALL |XFS_QMOPT_INHERIT , &udqp, &gdqp, &pdqp);if (error)
@@ -1148,8 +1148,8 @@ xfs_create_tmpfile(/* * Make sure that we have allocated dquot(s) on disk. */ - error =xfs_qm_vop_dqalloc (dp,mapped_fsuid (mnt_userns), -mapped_fsgid (mnt_userns), prid, + error =xfs_qm_vop_dqalloc (dp,mapped_fsuid (mnt_userns, &init_user_ns), +mapped_fsgid (mnt_userns, &init_user_ns), prid,XFS_QMOPT_QUOTALL |XFS_QMOPT_INHERIT , &udqp, &gdqp, &pdqp);if (error)
fs/xfs/xfs_linux.h +1 -0
@@ -61,6 +61,7 @@ typedef __u32 xfs_nlink_t;#include <linux/ratelimit.h> #include <linux/rhashtable.h> #include <linux/xattr.h> +#include <linux/mnt_idmapping.h> #include <asm/page.h> #include <asm/div64.h>
fs/xfs/xfs_log_cil.c +3 -3
@@ -1442,9 +1442,9 @@ xlog_cil_force_seq(*/ bool xfs_log_item_in_current_chkpt ( -struct xfs_log_item *lip) +struct xfs_log_item *lip) { -struct xfs_cil_ctx *ctx = lip->li_mountp->m_log->l_cilp->xc_ctx; +struct xfs_cil *cil = lip->li_mountp->m_log->l_cilp;if (list_empty (&lip->li_cil))return false;
@@ -1454,7 +1454,7 @@ xfs_log_item_in_current_chkpt(* first checkpoint it is written to. Hence if it is different to the * current sequence, we're in a new checkpoint. */ -return lip->li_seq == ctx->sequence; +return lip->li_seq ==READ_ONCE (cil->xc_current_sequence); }/*
fs/xfs/xfs_super.c +16 -5
@@ -1768,7 +1768,15 @@ static intxfs_remount_ro ( struct xfs_mount *mp) { -int error; +struct xfs_icwalk icw = { + .icw_flags =XFS_ICWALK_FLAG_SYNC , + }; +int error; + +/* Flush all the dirty data to disk. */ + error =sync_filesystem (mp->m_super); +if (error) +return error;/* * Cancel background eofb scanning so it cannot race with the final
@@ -1776,8 +1784,13 @@ xfs_remount_ro(*/ xfs_blockgc_stop (mp); -/* Get rid of any leftover CoW reservations... */ - error =xfs_blockgc_free_space (mp,NULL ); +/* +* Clear out all remaining COW staging extents and speculative post-EOF +* preallocations so that we don't leave inodes requiring inactivation +* cleanups during reclaim on a read-only mount. We must process every +* cached inode, so this requires a synchronous cache scan. +*/ + error =xfs_blockgc_free_space (mp, &icw);if (error) {xfs_force_shutdown (mp,SHUTDOWN_CORRUPT_INCORE );return error;
@@ -1843,8 +1856,6 @@ xfs_fs_reconfigure(if (error)return error; -sync_filesystem (mp->m_super); -/* inode32 -> inode64 */ if (xfs_has_small_inums (mp) && !xfs_has_small_inums (new_mp)) { mp->m_features &= ~XFS_FEAT_SMALL_INUMS ;
fs/xfs/xfs_symlink.c +2 -2
@@ -184,8 +184,8 @@ xfs_symlink(/* * Make sure that we have allocated dquot(s) on disk. */ - error =xfs_qm_vop_dqalloc (dp,mapped_fsuid (mnt_userns), -mapped_fsgid (mnt_userns), prid, + error =xfs_qm_vop_dqalloc (dp,mapped_fsuid (mnt_userns, &init_user_ns), +mapped_fsgid (mnt_userns, &init_user_ns), prid,XFS_QMOPT_QUOTALL |XFS_QMOPT_INHERIT , &udqp, &gdqp, &pdqp);if (error)
include/linux/fs.h +40 -101
208 lines not on this page · raw message
include/linux/mnt_idmapping.h new file +234 -0
234 lines not on this page · raw message
include/linux/posix_acl_xattr.h +4 -0
@@ -34,15 +34,19 @@ posix_acl_xattr_count(size_t size)#ifdef CONFIG_FS_POSIX_ACL void posix_acl_fix_xattr_from_user (struct user_namespace *mnt_userns, +struct inode *inode,void *value,size_t size);void posix_acl_fix_xattr_to_user (struct user_namespace *mnt_userns, +struct inode *inode,void *value,size_t size);#else static inline void posix_acl_fix_xattr_from_user (struct user_namespace *mnt_userns, +struct inode *inode,void *value,size_t size) { }static inline void posix_acl_fix_xattr_to_user (struct user_namespace *mnt_userns, +struct inode *inode,void *value,size_t size) { }
kernel/time/tick-sched.c +0 -1
@@ -509,7 +509,6 @@ void __init tick_nohz_full_setup(cpumask_var_t cpumask)cpumask_copy (tick_nohz_full_mask, cpumask); tick_nohz_full_running = true; } -EXPORT_SYMBOL_GPL (tick_nohz_full_setup);static int tick_nohz_cpu_down (unsigned int cpu) {
security/commoncap.c +9 -6
@@ -24,6 +24,7 @@#include <linux/user_namespace.h> #include <linux/binfmts.h> #include <linux/personality.h> +#include <linux/mnt_idmapping.h> /* * If a non-root user executes a setuid-root binary in
@@ -418,7 +419,7 @@ int cap_inode_getsecurity(struct user_namespace *mnt_userns, kroot =make_kuid (fs_ns, root);/* If this is an idmapped mount shift the kuid. */ - kroot =kuid_into_mnt (mnt_userns, kroot); + kroot =mapped_kuid_fs (mnt_userns, fs_ns, kroot);/* If the root kuid maps to a valid uid in current ns, then return * this as a nscap. */
@@ -488,6 +489,7 @@ int cap_inode_getsecurity(struct user_namespace *mnt_userns,* @size: size of @ivalue * @task_ns: user namespace of the caller * @mnt_userns: user namespace of the mount the inode was found from +* @fs_userns: user namespace of the filesystem * * If the inode has been found through an idmapped mount the user namespace of * the vfsmount must be passed through @mnt_userns. This function will then
@@ -497,7 +499,8 @@ int cap_inode_getsecurity(struct user_namespace *mnt_userns,*/ static kuid_t rootid_from_xattr (const void *value,size_t size,struct user_namespace *task_ns, -struct user_namespace *mnt_userns) +struct user_namespace *mnt_userns, +struct user_namespace *fs_userns) {const struct vfs_ns_cap_data *nscap = value;kuid_t rootkid;
@@ -507,7 +510,7 @@ static kuid_t rootid_from_xattr(const void *value, size_t size, rootid =le32_to_cpu (nscap->rootid); rootkid =make_kuid (task_ns, rootid); -return kuid_from_mnt (mnt_userns, rootkid); +return mapped_kuid_user (mnt_userns, fs_userns, rootkid); }static bool validheader (size_t size,const struct vfs_cap_data *cap)
@@ -553,12 +556,12 @@ int cap_convert_nscap(struct user_namespace *mnt_userns, struct dentry *dentry,return -EINVAL ;if (!capable_wrt_inode_uidgid (mnt_userns, inode,CAP_SETFCAP ))return -EPERM ; -if (size ==XATTR_CAPS_SZ_2 && (mnt_userns == &init_user_ns)) +if (size ==XATTR_CAPS_SZ_2 && (mnt_userns == fs_ns))if (ns_capable (inode->i_sb->s_user_ns,CAP_SETFCAP ))/* user is privileged, just write the v2 */ return size; - rootid =rootid_from_xattr (*ivalue, size, task_ns, mnt_userns); + rootid =rootid_from_xattr (*ivalue, size, task_ns, mnt_userns, fs_ns);if (!uid_valid (rootid))return -EINVAL ;
@@ -699,7 +702,7 @@ int get_vfs_caps_from_disk(struct user_namespace *mnt_userns,/* Limit the caps to the mounter of the filesystem * or the more limited uid specified in the xattr. */ - rootkuid =kuid_into_mnt (mnt_userns, rootkuid); + rootkuid =mapped_kuid_fs (mnt_userns, fs_ns, rootkuid);if (!rootid_owns_currentns (rootkuid))return -ENODATA ;