Commit e4236f97 authored by Christian Brauner's avatar Christian Brauner Committed by Christian Brauner (Microsoft)

Merge branch 'fs.vfsuid.conversion' into for-next

parents 03fd1402 eb7718cd
...@@ -716,7 +716,7 @@ void do_coredump(const kernel_siginfo_t *siginfo) ...@@ -716,7 +716,7 @@ void do_coredump(const kernel_siginfo_t *siginfo)
* filesystem. * filesystem.
*/ */
mnt_userns = file_mnt_user_ns(cprm.file); mnt_userns = file_mnt_user_ns(cprm.file);
if (!uid_eq(i_uid_into_mnt(mnt_userns, inode), if (!vfsuid_eq_kuid(i_uid_into_vfsuid(mnt_userns, inode),
current_fsuid())) { current_fsuid())) {
pr_info_ratelimited("Core dump to %s aborted: cannot preserve file owner\n", pr_info_ratelimited("Core dump to %s aborted: cannot preserve file owner\n",
cn.corename); cn.corename);
......
...@@ -1591,8 +1591,8 @@ static void bprm_fill_uid(struct linux_binprm *bprm, struct file *file) ...@@ -1591,8 +1591,8 @@ static void bprm_fill_uid(struct linux_binprm *bprm, struct file *file)
struct user_namespace *mnt_userns; struct user_namespace *mnt_userns;
struct inode *inode = file_inode(file); struct inode *inode = file_inode(file);
unsigned int mode; unsigned int mode;
kuid_t uid; vfsuid_t vfsuid;
kgid_t gid; vfsgid_t vfsgid;
if (!mnt_may_suid(file->f_path.mnt)) if (!mnt_may_suid(file->f_path.mnt))
return; return;
...@@ -1611,23 +1611,23 @@ static void bprm_fill_uid(struct linux_binprm *bprm, struct file *file) ...@@ -1611,23 +1611,23 @@ static void bprm_fill_uid(struct linux_binprm *bprm, struct file *file)
/* reload atomically mode/uid/gid now that lock held */ /* reload atomically mode/uid/gid now that lock held */
mode = inode->i_mode; mode = inode->i_mode;
uid = i_uid_into_mnt(mnt_userns, inode); vfsuid = i_uid_into_vfsuid(mnt_userns, inode);
gid = i_gid_into_mnt(mnt_userns, inode); vfsgid = i_gid_into_vfsgid(mnt_userns, inode);
inode_unlock(inode); inode_unlock(inode);
/* We ignore suid/sgid if there are no mappings for them in the ns */ /* We ignore suid/sgid if there are no mappings for them in the ns */
if (!kuid_has_mapping(bprm->cred->user_ns, uid) || if (!vfsuid_has_mapping(bprm->cred->user_ns, vfsuid) ||
!kgid_has_mapping(bprm->cred->user_ns, gid)) !vfsgid_has_mapping(bprm->cred->user_ns, vfsgid))
return; return;
if (mode & S_ISUID) { if (mode & S_ISUID) {
bprm->per_clear |= PER_CLEAR_ON_SETID; bprm->per_clear |= PER_CLEAR_ON_SETID;
bprm->cred->euid = uid; bprm->cred->euid = vfsuid_into_kuid(vfsuid);
} }
if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) { if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
bprm->per_clear |= PER_CLEAR_ON_SETID; bprm->per_clear |= PER_CLEAR_ON_SETID;
bprm->cred->egid = gid; bprm->cred->egid = vfsgid_into_kgid(vfsgid);
} }
} }
......
...@@ -99,7 +99,7 @@ int fuse_set_acl(struct user_namespace *mnt_userns, struct dentry *dentry, ...@@ -99,7 +99,7 @@ int fuse_set_acl(struct user_namespace *mnt_userns, struct dentry *dentry,
return ret; return ret;
} }
if (!in_group_p(i_gid_into_mnt(&init_user_ns, inode)) && if (!vfsgid_in_group_p(i_gid_into_vfsgid(&init_user_ns, inode)) &&
!capable_wrt_inode_uidgid(&init_user_ns, inode, CAP_FSETID)) !capable_wrt_inode_uidgid(&init_user_ns, inode, CAP_FSETID))
extra_flags |= FUSE_SETXATTR_ACL_KILL_SGID; extra_flags |= FUSE_SETXATTR_ACL_KILL_SGID;
......
...@@ -2326,15 +2326,15 @@ EXPORT_SYMBOL(inode_init_owner); ...@@ -2326,15 +2326,15 @@ EXPORT_SYMBOL(inode_init_owner);
bool inode_owner_or_capable(struct user_namespace *mnt_userns, bool inode_owner_or_capable(struct user_namespace *mnt_userns,
const struct inode *inode) const struct inode *inode)
{ {
kuid_t i_uid; vfsuid_t vfsuid;
struct user_namespace *ns; struct user_namespace *ns;
i_uid = i_uid_into_mnt(mnt_userns, inode); vfsuid = i_uid_into_vfsuid(mnt_userns, inode);
if (uid_eq(current_fsuid(), i_uid)) if (vfsuid_eq_kuid(vfsuid, current_fsuid()))
return true; return true;
ns = current_user_ns(); ns = current_user_ns();
if (kuid_has_mapping(ns, i_uid) && ns_capable(ns, CAP_FOWNER)) if (vfsuid_has_mapping(ns, vfsuid) && ns_capable(ns, CAP_FOWNER))
return true; return true;
return false; return false;
} }
......
...@@ -336,11 +336,11 @@ static int acl_permission_check(struct user_namespace *mnt_userns, ...@@ -336,11 +336,11 @@ static int acl_permission_check(struct user_namespace *mnt_userns,
struct inode *inode, int mask) struct inode *inode, int mask)
{ {
unsigned int mode = inode->i_mode; unsigned int mode = inode->i_mode;
kuid_t i_uid; vfsuid_t vfsuid;
/* Are we the owner? If so, ACL's don't matter */ /* Are we the owner? If so, ACL's don't matter */
i_uid = i_uid_into_mnt(mnt_userns, inode); vfsuid = i_uid_into_vfsuid(mnt_userns, inode);
if (likely(uid_eq(current_fsuid(), i_uid))) { if (likely(vfsuid_eq_kuid(vfsuid, current_fsuid()))) {
mask &= 7; mask &= 7;
mode >>= 6; mode >>= 6;
return (mask & ~mode) ? -EACCES : 0; return (mask & ~mode) ? -EACCES : 0;
...@@ -362,8 +362,8 @@ static int acl_permission_check(struct user_namespace *mnt_userns, ...@@ -362,8 +362,8 @@ static int acl_permission_check(struct user_namespace *mnt_userns,
* about? Need to check group ownership if so. * about? Need to check group ownership if so.
*/ */
if (mask & (mode ^ (mode >> 3))) { if (mask & (mode ^ (mode >> 3))) {
kgid_t kgid = i_gid_into_mnt(mnt_userns, inode); vfsgid_t vfsgid = i_gid_into_vfsgid(mnt_userns, inode);
if (in_group_p(kgid)) if (vfsgid_in_group_p(vfsgid))
mode >>= 3; mode >>= 3;
} }
...@@ -581,7 +581,7 @@ struct nameidata { ...@@ -581,7 +581,7 @@ struct nameidata {
struct nameidata *saved; struct nameidata *saved;
unsigned root_seq; unsigned root_seq;
int dfd; int dfd;
kuid_t dir_uid; vfsuid_t dir_vfsuid;
umode_t dir_mode; umode_t dir_mode;
} __randomize_layout; } __randomize_layout;
...@@ -1095,15 +1095,15 @@ fs_initcall(init_fs_namei_sysctls); ...@@ -1095,15 +1095,15 @@ fs_initcall(init_fs_namei_sysctls);
static inline int may_follow_link(struct nameidata *nd, const struct inode *inode) static inline int may_follow_link(struct nameidata *nd, const struct inode *inode)
{ {
struct user_namespace *mnt_userns; struct user_namespace *mnt_userns;
kuid_t i_uid; vfsuid_t vfsuid;
if (!sysctl_protected_symlinks) if (!sysctl_protected_symlinks)
return 0; return 0;
mnt_userns = mnt_user_ns(nd->path.mnt); mnt_userns = mnt_user_ns(nd->path.mnt);
i_uid = i_uid_into_mnt(mnt_userns, inode); vfsuid = i_uid_into_vfsuid(mnt_userns, inode);
/* Allowed if owner and follower match. */ /* Allowed if owner and follower match. */
if (uid_eq(current_cred()->fsuid, i_uid)) if (vfsuid_eq_kuid(vfsuid, current_fsuid()))
return 0; return 0;
/* Allowed if parent directory not sticky and world-writable. */ /* Allowed if parent directory not sticky and world-writable. */
...@@ -1111,7 +1111,7 @@ static inline int may_follow_link(struct nameidata *nd, const struct inode *inod ...@@ -1111,7 +1111,7 @@ static inline int may_follow_link(struct nameidata *nd, const struct inode *inod
return 0; return 0;
/* Allowed if parent directory and link owner match. */ /* Allowed if parent directory and link owner match. */
if (uid_valid(nd->dir_uid) && uid_eq(nd->dir_uid, i_uid)) if (vfsuid_valid(nd->dir_vfsuid) && vfsuid_eq(nd->dir_vfsuid, vfsuid))
return 0; return 0;
if (nd->flags & LOOKUP_RCU) if (nd->flags & LOOKUP_RCU)
...@@ -1183,8 +1183,8 @@ int may_linkat(struct user_namespace *mnt_userns, const struct path *link) ...@@ -1183,8 +1183,8 @@ int may_linkat(struct user_namespace *mnt_userns, const struct path *link)
struct inode *inode = link->dentry->d_inode; struct inode *inode = link->dentry->d_inode;
/* Inode writeback is not safe when the uid or gid are invalid. */ /* Inode writeback is not safe when the uid or gid are invalid. */
if (!uid_valid(i_uid_into_mnt(mnt_userns, inode)) || if (!vfsuid_valid(i_uid_into_vfsuid(mnt_userns, inode)) ||
!gid_valid(i_gid_into_mnt(mnt_userns, inode))) !vfsgid_valid(i_gid_into_vfsgid(mnt_userns, inode)))
return -EOVERFLOW; return -EOVERFLOW;
if (!sysctl_protected_hardlinks) if (!sysctl_protected_hardlinks)
...@@ -1232,13 +1232,13 @@ static int may_create_in_sticky(struct user_namespace *mnt_userns, ...@@ -1232,13 +1232,13 @@ static int may_create_in_sticky(struct user_namespace *mnt_userns,
struct nameidata *nd, struct inode *const inode) struct nameidata *nd, struct inode *const inode)
{ {
umode_t dir_mode = nd->dir_mode; umode_t dir_mode = nd->dir_mode;
kuid_t dir_uid = nd->dir_uid; vfsuid_t dir_vfsuid = nd->dir_vfsuid;
if ((!sysctl_protected_fifos && S_ISFIFO(inode->i_mode)) || if ((!sysctl_protected_fifos && S_ISFIFO(inode->i_mode)) ||
(!sysctl_protected_regular && S_ISREG(inode->i_mode)) || (!sysctl_protected_regular && S_ISREG(inode->i_mode)) ||
likely(!(dir_mode & S_ISVTX)) || likely(!(dir_mode & S_ISVTX)) ||
uid_eq(i_uid_into_mnt(mnt_userns, inode), dir_uid) || vfsuid_eq(i_uid_into_vfsuid(mnt_userns, inode), dir_vfsuid) ||
uid_eq(current_fsuid(), i_uid_into_mnt(mnt_userns, inode))) vfsuid_eq_kuid(i_uid_into_vfsuid(mnt_userns, inode), current_fsuid()))
return 0; return 0;
if (likely(dir_mode & 0002) || if (likely(dir_mode & 0002) ||
...@@ -2307,7 +2307,7 @@ static int link_path_walk(const char *name, struct nameidata *nd) ...@@ -2307,7 +2307,7 @@ static int link_path_walk(const char *name, struct nameidata *nd)
OK: OK:
/* pathname or trailing symlink, done */ /* pathname or trailing symlink, done */
if (!depth) { if (!depth) {
nd->dir_uid = i_uid_into_mnt(mnt_userns, nd->inode); nd->dir_vfsuid = i_uid_into_vfsuid(mnt_userns, nd->inode);
nd->dir_mode = nd->inode->i_mode; nd->dir_mode = nd->inode->i_mode;
nd->flags &= ~LOOKUP_PARENT; nd->flags &= ~LOOKUP_PARENT;
return 0; return 0;
...@@ -2885,9 +2885,9 @@ int __check_sticky(struct user_namespace *mnt_userns, struct inode *dir, ...@@ -2885,9 +2885,9 @@ int __check_sticky(struct user_namespace *mnt_userns, struct inode *dir,
{ {
kuid_t fsuid = current_fsuid(); kuid_t fsuid = current_fsuid();
if (uid_eq(i_uid_into_mnt(mnt_userns, inode), fsuid)) if (vfsuid_eq_kuid(i_uid_into_vfsuid(mnt_userns, inode), fsuid))
return 0; return 0;
if (uid_eq(i_uid_into_mnt(mnt_userns, dir), fsuid)) if (vfsuid_eq_kuid(i_uid_into_vfsuid(mnt_userns, dir), fsuid))
return 0; return 0;
return !capable_wrt_inode_uidgid(mnt_userns, inode, CAP_FOWNER); return !capable_wrt_inode_uidgid(mnt_userns, inode, CAP_FOWNER);
} }
...@@ -2926,8 +2926,8 @@ static int may_delete(struct user_namespace *mnt_userns, struct inode *dir, ...@@ -2926,8 +2926,8 @@ static int may_delete(struct user_namespace *mnt_userns, struct inode *dir,
BUG_ON(victim->d_parent->d_inode != dir); BUG_ON(victim->d_parent->d_inode != dir);
/* Inode writeback is not safe when the uid or gid are invalid. */ /* Inode writeback is not safe when the uid or gid are invalid. */
if (!uid_valid(i_uid_into_mnt(mnt_userns, inode)) || if (!vfsuid_valid(i_uid_into_vfsuid(mnt_userns, inode)) ||
!gid_valid(i_gid_into_mnt(mnt_userns, inode))) !vfsgid_valid(i_gid_into_vfsgid(mnt_userns, inode)))
return -EOVERFLOW; return -EOVERFLOW;
audit_inode_child(dir, victim, AUDIT_TYPE_CHILD_DELETE); audit_inode_child(dir, victim, AUDIT_TYPE_CHILD_DELETE);
......
...@@ -1104,13 +1104,18 @@ void ovl_copyattr(struct inode *inode) ...@@ -1104,13 +1104,18 @@ void ovl_copyattr(struct inode *inode)
struct path realpath; struct path realpath;
struct inode *realinode; struct inode *realinode;
struct user_namespace *real_mnt_userns; struct user_namespace *real_mnt_userns;
vfsuid_t vfsuid;
vfsgid_t vfsgid;
ovl_i_path_real(inode, &realpath); ovl_i_path_real(inode, &realpath);
realinode = d_inode(realpath.dentry); realinode = d_inode(realpath.dentry);
real_mnt_userns = mnt_user_ns(realpath.mnt); real_mnt_userns = mnt_user_ns(realpath.mnt);
inode->i_uid = i_uid_into_mnt(real_mnt_userns, realinode); vfsuid = i_uid_into_vfsuid(real_mnt_userns, realinode);
inode->i_gid = i_gid_into_mnt(real_mnt_userns, realinode); vfsgid = i_gid_into_vfsgid(real_mnt_userns, realinode);
inode->i_uid = vfsuid_into_kuid(vfsuid);
inode->i_gid = vfsgid_into_kgid(vfsgid);
inode->i_mode = realinode->i_mode; inode->i_mode = realinode->i_mode;
inode->i_atime = realinode->i_atime; inode->i_atime = realinode->i_atime;
inode->i_mtime = realinode->i_mtime; inode->i_mtime = realinode->i_mtime;
......
...@@ -429,7 +429,7 @@ static bool allow_file_dedupe(struct file *file) ...@@ -429,7 +429,7 @@ static bool allow_file_dedupe(struct file *file)
return true; return true;
if (file->f_mode & FMODE_WRITE) if (file->f_mode & FMODE_WRITE)
return true; return true;
if (uid_eq(current_fsuid(), i_uid_into_mnt(mnt_userns, inode))) if (vfsuid_eq_kuid(i_uid_into_vfsuid(mnt_userns, inode), current_fsuid()))
return true; return true;
if (!inode_permission(mnt_userns, inode, MAY_WRITE)) if (!inode_permission(mnt_userns, inode, MAY_WRITE))
return true; return true;
......
...@@ -44,12 +44,15 @@ ...@@ -44,12 +44,15 @@
void generic_fillattr(struct user_namespace *mnt_userns, struct inode *inode, void generic_fillattr(struct user_namespace *mnt_userns, struct inode *inode,
struct kstat *stat) struct kstat *stat)
{ {
vfsuid_t vfsuid = i_uid_into_vfsuid(mnt_userns, inode);
vfsgid_t vfsgid = i_gid_into_vfsgid(mnt_userns, inode);
stat->dev = inode->i_sb->s_dev; stat->dev = inode->i_sb->s_dev;
stat->ino = inode->i_ino; stat->ino = inode->i_ino;
stat->mode = inode->i_mode; stat->mode = inode->i_mode;
stat->nlink = inode->i_nlink; stat->nlink = inode->i_nlink;
stat->uid = i_uid_into_mnt(mnt_userns, inode); stat->uid = vfsuid_into_kuid(vfsuid);
stat->gid = i_gid_into_mnt(mnt_userns, inode); stat->gid = vfsgid_into_kgid(vfsgid);
stat->rdev = inode->i_rdev; stat->rdev = inode->i_rdev;
stat->size = i_size_read(inode); stat->size = i_size_read(inode);
stat->atime = inode->i_atime; stat->atime = inode->i_atime;
......
...@@ -1612,23 +1612,6 @@ static inline void i_gid_write(struct inode *inode, gid_t gid) ...@@ -1612,23 +1612,6 @@ static inline void i_gid_write(struct inode *inode, gid_t gid)
inode->i_gid = make_kgid(i_user_ns(inode), gid); inode->i_gid = make_kgid(i_user_ns(inode), gid);
} }
/**
* i_uid_into_mnt - map an inode's i_uid down into a mnt_userns
* @mnt_userns: user namespace of the mount the inode was found from
* @inode: inode to map
*
* Note, this will eventually be removed completely in favor of the type-safe
* i_uid_into_vfsuid().
*
* Return: the inode's i_uid mapped down according to @mnt_userns.
* If the inode's i_uid has no mapping INVALID_UID is returned.
*/
static inline kuid_t i_uid_into_mnt(struct user_namespace *mnt_userns,
const struct inode *inode)
{
return AS_KUIDT(make_vfsuid(mnt_userns, i_user_ns(inode), inode->i_uid));
}
/** /**
* i_uid_into_vfsuid - map an inode's i_uid down into a mnt_userns * i_uid_into_vfsuid - map an inode's i_uid down into a mnt_userns
* @mnt_userns: user namespace of the mount the inode was found from * @mnt_userns: user namespace of the mount the inode was found from
...@@ -1681,23 +1664,6 @@ static inline void i_uid_update(struct user_namespace *mnt_userns, ...@@ -1681,23 +1664,6 @@ static inline void i_uid_update(struct user_namespace *mnt_userns,
attr->ia_vfsuid); attr->ia_vfsuid);
} }
/**
* i_gid_into_mnt - map an inode's i_gid down into a mnt_userns
* @mnt_userns: user namespace of the mount the inode was found from
* @inode: inode to map
*
* Note, this will eventually be removed completely in favor of the type-safe
* i_gid_into_vfsgid().
*
* Return: the inode's i_gid mapped down according to @mnt_userns.
* If the inode's i_gid has no mapping INVALID_GID is returned.
*/
static inline kgid_t i_gid_into_mnt(struct user_namespace *mnt_userns,
const struct inode *inode)
{
return AS_KGIDT(make_vfsgid(mnt_userns, i_user_ns(inode), inode->i_gid));
}
/** /**
* i_gid_into_vfsgid - map an inode's i_gid down into a mnt_userns * i_gid_into_vfsgid - map an inode's i_gid down into a mnt_userns
* @mnt_userns: user namespace of the mount the inode was found from * @mnt_userns: user namespace of the mount the inode was found from
......
...@@ -98,6 +98,26 @@ static inline bool vfsgid_eq_kgid(vfsgid_t vfsgid, kgid_t kgid) ...@@ -98,6 +98,26 @@ static inline bool vfsgid_eq_kgid(vfsgid_t vfsgid, kgid_t kgid)
return vfsgid_valid(vfsgid) && __vfsgid_val(vfsgid) == __kgid_val(kgid); return vfsgid_valid(vfsgid) && __vfsgid_val(vfsgid) == __kgid_val(kgid);
} }
static inline bool vfsuid_gt_kuid(vfsuid_t vfsuid, kuid_t kuid)
{
return __vfsuid_val(vfsuid) > __kuid_val(kuid);
}
static inline bool vfsgid_gt_kgid(vfsgid_t vfsgid, kgid_t kgid)
{
return __vfsgid_val(vfsgid) > __kgid_val(kgid);
}
static inline bool vfsuid_lt_kuid(vfsuid_t vfsuid, kuid_t kuid)
{
return __vfsuid_val(vfsuid) < __kuid_val(kuid);
}
static inline bool vfsgid_lt_kgid(vfsgid_t vfsgid, kgid_t kgid)
{
return __vfsgid_val(vfsgid) < __kgid_val(kgid);
}
/* /*
* vfs{g,u}ids are created from k{g,u}ids. * vfs{g,u}ids are created from k{g,u}ids.
* We don't allow them to be created from regular {u,g}id. * We don't allow them to be created from regular {u,g}id.
...@@ -208,13 +228,6 @@ static inline vfsuid_t make_vfsuid(struct user_namespace *mnt_userns, ...@@ -208,13 +228,6 @@ static inline vfsuid_t make_vfsuid(struct user_namespace *mnt_userns,
return VFSUIDT_INIT(make_kuid(mnt_userns, uid)); return VFSUIDT_INIT(make_kuid(mnt_userns, uid));
} }
static inline kuid_t mapped_kuid_fs(struct user_namespace *mnt_userns,
struct user_namespace *fs_userns,
kuid_t kuid)
{
return AS_KUIDT(make_vfsuid(mnt_userns, fs_userns, kuid));
}
/** /**
* make_vfsgid - map a filesystem kgid into a mnt_userns * make_vfsgid - map a filesystem kgid into a mnt_userns
* @mnt_userns: the mount's idmapping * @mnt_userns: the mount's idmapping
...@@ -253,13 +266,6 @@ static inline vfsgid_t make_vfsgid(struct user_namespace *mnt_userns, ...@@ -253,13 +266,6 @@ static inline vfsgid_t make_vfsgid(struct user_namespace *mnt_userns,
return VFSGIDT_INIT(make_kgid(mnt_userns, gid)); return VFSGIDT_INIT(make_kgid(mnt_userns, gid));
} }
static inline kgid_t mapped_kgid_fs(struct user_namespace *mnt_userns,
struct user_namespace *fs_userns,
kgid_t kgid)
{
return AS_KGIDT(make_vfsgid(mnt_userns, fs_userns, kgid));
}
/** /**
* from_vfsuid - map a vfsuid into the filesystem idmapping * from_vfsuid - map a vfsuid into the filesystem idmapping
* @mnt_userns: the mount's idmapping * @mnt_userns: the mount's idmapping
...@@ -287,33 +293,6 @@ static inline kuid_t from_vfsuid(struct user_namespace *mnt_userns, ...@@ -287,33 +293,6 @@ static inline kuid_t from_vfsuid(struct user_namespace *mnt_userns,
return make_kuid(fs_userns, uid); return make_kuid(fs_userns, uid);
} }
/**
* mapped_kuid_user - map a user kuid into a mnt_userns
* @mnt_userns: the mount's idmapping
* @fs_userns: the filesystem's idmapping
* @kuid : kuid to be mapped
*
* Use the idmapping of @mnt_userns to remap a @kuid into @fs_userns. Use this
* function when preparing a @kuid to be written to disk or inode.
*
* If no_idmapping() determines that this is not an idmapped mount we can
* simply return @kuid unchanged.
* If initial_idmapping() tells us that the filesystem is not mounted with an
* idmapping we know the value of @kuid won't change when calling
* make_kuid() so we can simply retrieve the value via KUIDT_INIT()
* directly.
*
* Return: @kuid mapped according to @mnt_userns.
* If @kuid has no mapping in either @mnt_userns or @fs_userns INVALID_UID is
* returned.
*/
static inline kuid_t mapped_kuid_user(struct user_namespace *mnt_userns,
struct user_namespace *fs_userns,
kuid_t kuid)
{
return from_vfsuid(mnt_userns, fs_userns, VFSUIDT_INIT(kuid));
}
/** /**
* vfsuid_has_fsmapping - check whether a vfsuid maps into the filesystem * vfsuid_has_fsmapping - check whether a vfsuid maps into the filesystem
* @mnt_userns: the mount's idmapping * @mnt_userns: the mount's idmapping
...@@ -333,6 +312,12 @@ static inline bool vfsuid_has_fsmapping(struct user_namespace *mnt_userns, ...@@ -333,6 +312,12 @@ static inline bool vfsuid_has_fsmapping(struct user_namespace *mnt_userns,
return uid_valid(from_vfsuid(mnt_userns, fs_userns, vfsuid)); return uid_valid(from_vfsuid(mnt_userns, fs_userns, vfsuid));
} }
static inline bool vfsuid_has_mapping(struct user_namespace *userns,
vfsuid_t vfsuid)
{
return from_kuid(userns, AS_KUIDT(vfsuid)) != (uid_t)-1;
}
/** /**
* vfsuid_into_kuid - convert vfsuid into kuid * vfsuid_into_kuid - convert vfsuid into kuid
* @vfsuid: the vfsuid to convert * @vfsuid: the vfsuid to convert
...@@ -373,33 +358,6 @@ static inline kgid_t from_vfsgid(struct user_namespace *mnt_userns, ...@@ -373,33 +358,6 @@ static inline kgid_t from_vfsgid(struct user_namespace *mnt_userns,
return make_kgid(fs_userns, gid); return make_kgid(fs_userns, gid);
} }
/**
* mapped_kgid_user - map a user kgid into a mnt_userns
* @mnt_userns: the mount's idmapping
* @fs_userns: the filesystem's idmapping
* @kgid : kgid to be mapped
*
* Use the idmapping of @mnt_userns to remap a @kgid into @fs_userns. Use this
* function when preparing a @kgid to be written to disk or inode.
*
* If no_idmapping() determines that this is not an idmapped mount we can
* simply return @kgid unchanged.
* If initial_idmapping() tells us that the filesystem is not mounted with an
* idmapping we know the value of @kgid won't change when calling
* make_kgid() so we can simply retrieve the value via KGIDT_INIT()
* directly.
*
* Return: @kgid mapped according to @mnt_userns.
* If @kgid has no mapping in either @mnt_userns or @fs_userns INVALID_GID is
* returned.
*/
static inline kgid_t mapped_kgid_user(struct user_namespace *mnt_userns,
struct user_namespace *fs_userns,
kgid_t kgid)
{
return from_vfsgid(mnt_userns, fs_userns, VFSGIDT_INIT(kgid));
}
/** /**
* vfsgid_has_fsmapping - check whether a vfsgid maps into the filesystem * vfsgid_has_fsmapping - check whether a vfsgid maps into the filesystem
* @mnt_userns: the mount's idmapping * @mnt_userns: the mount's idmapping
...@@ -419,6 +377,12 @@ static inline bool vfsgid_has_fsmapping(struct user_namespace *mnt_userns, ...@@ -419,6 +377,12 @@ static inline bool vfsgid_has_fsmapping(struct user_namespace *mnt_userns,
return gid_valid(from_vfsgid(mnt_userns, fs_userns, vfsgid)); return gid_valid(from_vfsgid(mnt_userns, fs_userns, vfsgid));
} }
static inline bool vfsgid_has_mapping(struct user_namespace *userns,
vfsgid_t vfsgid)
{
return from_kgid(userns, AS_KGIDT(vfsgid)) != (gid_t)-1;
}
/** /**
* vfsgid_into_kgid - convert vfsgid into kgid * vfsgid_into_kgid - convert vfsgid into kgid
* @vfsgid: the vfsgid to convert * @vfsgid: the vfsgid to convert
......
...@@ -489,8 +489,8 @@ bool privileged_wrt_inode_uidgid(struct user_namespace *ns, ...@@ -489,8 +489,8 @@ bool privileged_wrt_inode_uidgid(struct user_namespace *ns,
struct user_namespace *mnt_userns, struct user_namespace *mnt_userns,
const struct inode *inode) const struct inode *inode)
{ {
return kuid_has_mapping(ns, i_uid_into_mnt(mnt_userns, inode)) && return vfsuid_has_mapping(ns, i_uid_into_vfsuid(mnt_userns, inode)) &&
kgid_has_mapping(ns, i_gid_into_mnt(mnt_userns, inode)); vfsgid_has_mapping(ns, i_gid_into_vfsgid(mnt_userns, inode));
} }
/** /**
......
...@@ -859,10 +859,10 @@ int apparmor_bprm_creds_for_exec(struct linux_binprm *bprm) ...@@ -859,10 +859,10 @@ int apparmor_bprm_creds_for_exec(struct linux_binprm *bprm)
const char *info = NULL; const char *info = NULL;
int error = 0; int error = 0;
bool unsafe = false; bool unsafe = false;
kuid_t i_uid = i_uid_into_mnt(file_mnt_user_ns(bprm->file), vfsuid_t vfsuid = i_uid_into_vfsuid(file_mnt_user_ns(bprm->file),
file_inode(bprm->file)); file_inode(bprm->file));
struct path_cond cond = { struct path_cond cond = {
i_uid, vfsuid_into_kuid(vfsuid),
file_inode(bprm->file)->i_mode file_inode(bprm->file)->i_mode
}; };
...@@ -970,7 +970,7 @@ int apparmor_bprm_creds_for_exec(struct linux_binprm *bprm) ...@@ -970,7 +970,7 @@ int apparmor_bprm_creds_for_exec(struct linux_binprm *bprm)
error = fn_for_each(label, profile, error = fn_for_each(label, profile,
aa_audit_file(profile, &nullperms, OP_EXEC, MAY_EXEC, aa_audit_file(profile, &nullperms, OP_EXEC, MAY_EXEC,
bprm->filename, NULL, new, bprm->filename, NULL, new,
i_uid, info, error)); vfsuid_into_kuid(vfsuid), info, error));
aa_put_label(new); aa_put_label(new);
goto done; goto done;
} }
......
...@@ -510,8 +510,10 @@ static int __file_path_perm(const char *op, struct aa_label *label, ...@@ -510,8 +510,10 @@ static int __file_path_perm(const char *op, struct aa_label *label,
{ {
struct aa_profile *profile; struct aa_profile *profile;
struct aa_perms perms = {}; struct aa_perms perms = {};
vfsuid_t vfsuid = i_uid_into_vfsuid(file_mnt_user_ns(file),
file_inode(file));
struct path_cond cond = { struct path_cond cond = {
.uid = i_uid_into_mnt(file_mnt_user_ns(file), file_inode(file)), .uid = vfsuid_into_kuid(vfsuid),
.mode = file_inode(file)->i_mode .mode = file_inode(file)->i_mode
}; };
char *buffer; char *buffer;
......
...@@ -225,8 +225,10 @@ static int common_perm(const char *op, const struct path *path, u32 mask, ...@@ -225,8 +225,10 @@ static int common_perm(const char *op, const struct path *path, u32 mask,
static int common_perm_cond(const char *op, const struct path *path, u32 mask) static int common_perm_cond(const char *op, const struct path *path, u32 mask)
{ {
struct user_namespace *mnt_userns = mnt_user_ns(path->mnt); struct user_namespace *mnt_userns = mnt_user_ns(path->mnt);
vfsuid_t vfsuid = i_uid_into_vfsuid(mnt_userns,
d_backing_inode(path->dentry));
struct path_cond cond = { struct path_cond cond = {
i_uid_into_mnt(mnt_userns, d_backing_inode(path->dentry)), vfsuid_into_kuid(vfsuid),
d_backing_inode(path->dentry)->i_mode d_backing_inode(path->dentry)->i_mode
}; };
...@@ -270,11 +272,13 @@ static int common_perm_rm(const char *op, const struct path *dir, ...@@ -270,11 +272,13 @@ static int common_perm_rm(const char *op, const struct path *dir,
struct inode *inode = d_backing_inode(dentry); struct inode *inode = d_backing_inode(dentry);
struct user_namespace *mnt_userns = mnt_user_ns(dir->mnt); struct user_namespace *mnt_userns = mnt_user_ns(dir->mnt);
struct path_cond cond = { }; struct path_cond cond = { };
vfsuid_t vfsuid;
if (!inode || !path_mediated_fs(dentry)) if (!inode || !path_mediated_fs(dentry))
return 0; return 0;
cond.uid = i_uid_into_mnt(mnt_userns, inode); vfsuid = i_uid_into_vfsuid(mnt_userns, inode);
cond.uid = vfsuid_into_kuid(vfsuid);
cond.mode = inode->i_mode; cond.mode = inode->i_mode;
return common_perm_dir_dentry(op, dir, dentry, mask, &cond); return common_perm_dir_dentry(op, dir, dentry, mask, &cond);
...@@ -368,20 +372,23 @@ static int apparmor_path_rename(const struct path *old_dir, struct dentry *old_d ...@@ -368,20 +372,23 @@ static int apparmor_path_rename(const struct path *old_dir, struct dentry *old_d
label = begin_current_label_crit_section(); label = begin_current_label_crit_section();
if (!unconfined(label)) { if (!unconfined(label)) {
struct user_namespace *mnt_userns = mnt_user_ns(old_dir->mnt); struct user_namespace *mnt_userns = mnt_user_ns(old_dir->mnt);
vfsuid_t vfsuid;
struct path old_path = { .mnt = old_dir->mnt, struct path old_path = { .mnt = old_dir->mnt,
.dentry = old_dentry }; .dentry = old_dentry };
struct path new_path = { .mnt = new_dir->mnt, struct path new_path = { .mnt = new_dir->mnt,
.dentry = new_dentry }; .dentry = new_dentry };
struct path_cond cond = { struct path_cond cond = {
i_uid_into_mnt(mnt_userns, d_backing_inode(old_dentry)), .mode = d_backing_inode(old_dentry)->i_mode
d_backing_inode(old_dentry)->i_mode
}; };
vfsuid = i_uid_into_vfsuid(mnt_userns, d_backing_inode(old_dentry));
cond.uid = vfsuid_into_kuid(vfsuid);
if (flags & RENAME_EXCHANGE) { if (flags & RENAME_EXCHANGE) {
struct path_cond cond_exchange = { struct path_cond cond_exchange = {
i_uid_into_mnt(mnt_userns, d_backing_inode(new_dentry)), .mode = d_backing_inode(new_dentry)->i_mode,
d_backing_inode(new_dentry)->i_mode
}; };
vfsuid = i_uid_into_vfsuid(mnt_userns, d_backing_inode(old_dentry));
cond_exchange.uid = vfsuid_into_kuid(vfsuid);
error = aa_path_perm(OP_RENAME_SRC, label, &new_path, 0, error = aa_path_perm(OP_RENAME_SRC, label, &new_path, 0,
MAY_READ | AA_MAY_GETATTR | MAY_WRITE | MAY_READ | AA_MAY_GETATTR | MAY_WRITE |
...@@ -447,10 +454,12 @@ static int apparmor_file_open(struct file *file) ...@@ -447,10 +454,12 @@ static int apparmor_file_open(struct file *file)
if (!unconfined(label)) { if (!unconfined(label)) {
struct user_namespace *mnt_userns = file_mnt_user_ns(file); struct user_namespace *mnt_userns = file_mnt_user_ns(file);
struct inode *inode = file_inode(file); struct inode *inode = file_inode(file);
vfsuid_t vfsuid;
struct path_cond cond = { struct path_cond cond = {
i_uid_into_mnt(mnt_userns, inode), .mode = inode->i_mode,
inode->i_mode
}; };
vfsuid = i_uid_into_vfsuid(mnt_userns, inode);
cond.uid = vfsuid_into_kuid(vfsuid);
error = aa_path_perm(OP_OPEN, label, &file->f_path, 0, error = aa_path_perm(OP_OPEN, label, &file->f_path, 0,
aa_map_file_to_perms(file), &cond); aa_map_file_to_perms(file), &cond);
......
...@@ -328,14 +328,16 @@ int cap_inode_killpriv(struct user_namespace *mnt_userns, struct dentry *dentry) ...@@ -328,14 +328,16 @@ int cap_inode_killpriv(struct user_namespace *mnt_userns, struct dentry *dentry)
return error; return error;
} }
static bool rootid_owns_currentns(kuid_t kroot) static bool rootid_owns_currentns(vfsuid_t rootvfsuid)
{ {
struct user_namespace *ns; struct user_namespace *ns;
kuid_t kroot;
if (!uid_valid(kroot)) if (!vfsuid_valid(rootvfsuid))
return false; return false;
for (ns = current_user_ns(); ; ns = ns->parent) { kroot = vfsuid_into_kuid(rootvfsuid);
for (ns = current_user_ns();; ns = ns->parent) {
if (from_kuid(ns, kroot) == 0) if (from_kuid(ns, kroot) == 0)
return true; return true;
if (ns == &init_user_ns) if (ns == &init_user_ns)
...@@ -381,6 +383,7 @@ int cap_inode_getsecurity(struct user_namespace *mnt_userns, ...@@ -381,6 +383,7 @@ int cap_inode_getsecurity(struct user_namespace *mnt_userns,
{ {
int size, ret; int size, ret;
kuid_t kroot; kuid_t kroot;
vfsuid_t vfsroot;
u32 nsmagic, magic; u32 nsmagic, magic;
uid_t root, mappedroot; uid_t root, mappedroot;
char *tmpbuf = NULL; char *tmpbuf = NULL;
...@@ -419,11 +422,11 @@ int cap_inode_getsecurity(struct user_namespace *mnt_userns, ...@@ -419,11 +422,11 @@ int cap_inode_getsecurity(struct user_namespace *mnt_userns,
kroot = make_kuid(fs_ns, root); kroot = make_kuid(fs_ns, root);
/* If this is an idmapped mount shift the kuid. */ /* If this is an idmapped mount shift the kuid. */
kroot = mapped_kuid_fs(mnt_userns, fs_ns, kroot); vfsroot = make_vfsuid(mnt_userns, fs_ns, kroot);
/* If the root kuid maps to a valid uid in current ns, then return /* If the root kuid maps to a valid uid in current ns, then return
* this as a nscap. */ * this as a nscap. */
mappedroot = from_kuid(current_user_ns(), kroot); mappedroot = from_kuid(current_user_ns(), vfsuid_into_kuid(vfsroot));
if (mappedroot != (uid_t)-1 && mappedroot != (uid_t)0) { if (mappedroot != (uid_t)-1 && mappedroot != (uid_t)0) {
size = sizeof(struct vfs_ns_cap_data); size = sizeof(struct vfs_ns_cap_data);
if (alloc) { if (alloc) {
...@@ -450,7 +453,7 @@ int cap_inode_getsecurity(struct user_namespace *mnt_userns, ...@@ -450,7 +453,7 @@ int cap_inode_getsecurity(struct user_namespace *mnt_userns,
goto out_free; goto out_free;
} }
if (!rootid_owns_currentns(kroot)) { if (!rootid_owns_currentns(vfsroot)) {
size = -EOVERFLOW; size = -EOVERFLOW;
goto out_free; goto out_free;
} }
...@@ -488,29 +491,17 @@ int cap_inode_getsecurity(struct user_namespace *mnt_userns, ...@@ -488,29 +491,17 @@ int cap_inode_getsecurity(struct user_namespace *mnt_userns,
* @value: vfs caps value which may be modified by this function * @value: vfs caps value which may be modified by this function
* @size: size of @ivalue * @size: size of @ivalue
* @task_ns: user namespace of the caller * @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
* take care to map the inode according to @mnt_userns before checking
* permissions. On non-idmapped mounts or if permission checking is to be
* performed on the raw inode simply passs init_user_ns.
*/ */
static kuid_t rootid_from_xattr(const void *value, size_t size, static vfsuid_t rootid_from_xattr(const void *value, size_t size,
struct user_namespace *task_ns, struct user_namespace *task_ns)
struct user_namespace *mnt_userns,
struct user_namespace *fs_userns)
{ {
const struct vfs_ns_cap_data *nscap = value; const struct vfs_ns_cap_data *nscap = value;
kuid_t rootkid;
uid_t rootid = 0; uid_t rootid = 0;
if (size == XATTR_CAPS_SZ_3) if (size == XATTR_CAPS_SZ_3)
rootid = le32_to_cpu(nscap->rootid); rootid = le32_to_cpu(nscap->rootid);
rootkid = make_kuid(task_ns, rootid); return VFSUIDT_INIT(make_kuid(task_ns, rootid));
return mapped_kuid_user(mnt_userns, fs_userns, rootkid);
} }
static bool validheader(size_t size, const struct vfs_cap_data *cap) static bool validheader(size_t size, const struct vfs_cap_data *cap)
...@@ -548,6 +539,7 @@ int cap_convert_nscap(struct user_namespace *mnt_userns, struct dentry *dentry, ...@@ -548,6 +539,7 @@ int cap_convert_nscap(struct user_namespace *mnt_userns, struct dentry *dentry,
struct user_namespace *task_ns = current_user_ns(), struct user_namespace *task_ns = current_user_ns(),
*fs_ns = inode->i_sb->s_user_ns; *fs_ns = inode->i_sb->s_user_ns;
kuid_t rootid; kuid_t rootid;
vfsuid_t vfsrootid;
size_t newsize; size_t newsize;
if (!*ivalue) if (!*ivalue)
...@@ -561,7 +553,11 @@ int cap_convert_nscap(struct user_namespace *mnt_userns, struct dentry *dentry, ...@@ -561,7 +553,11 @@ int cap_convert_nscap(struct user_namespace *mnt_userns, struct dentry *dentry,
/* user is privileged, just write the v2 */ /* user is privileged, just write the v2 */
return size; return size;
rootid = rootid_from_xattr(*ivalue, size, task_ns, mnt_userns, fs_ns); vfsrootid = rootid_from_xattr(*ivalue, size, task_ns);
if (!vfsuid_valid(vfsrootid))
return -EINVAL;
rootid = from_vfsuid(mnt_userns, fs_ns, vfsrootid);
if (!uid_valid(rootid)) if (!uid_valid(rootid))
return -EINVAL; return -EINVAL;
...@@ -655,6 +651,7 @@ int get_vfs_caps_from_disk(struct user_namespace *mnt_userns, ...@@ -655,6 +651,7 @@ int get_vfs_caps_from_disk(struct user_namespace *mnt_userns,
struct vfs_ns_cap_data data, *nscaps = &data; struct vfs_ns_cap_data data, *nscaps = &data;
struct vfs_cap_data *caps = (struct vfs_cap_data *) &data; struct vfs_cap_data *caps = (struct vfs_cap_data *) &data;
kuid_t rootkuid; kuid_t rootkuid;
vfsuid_t rootvfsuid;
struct user_namespace *fs_ns; struct user_namespace *fs_ns;
memset(cpu_caps, 0, sizeof(struct cpu_vfs_cap_data)); memset(cpu_caps, 0, sizeof(struct cpu_vfs_cap_data));
...@@ -699,11 +696,15 @@ int get_vfs_caps_from_disk(struct user_namespace *mnt_userns, ...@@ -699,11 +696,15 @@ int get_vfs_caps_from_disk(struct user_namespace *mnt_userns,
default: default:
return -EINVAL; return -EINVAL;
} }
rootvfsuid = make_vfsuid(mnt_userns, fs_ns, rootkuid);
if (!vfsuid_valid(rootvfsuid))
return -ENODATA;
/* Limit the caps to the mounter of the filesystem /* Limit the caps to the mounter of the filesystem
* or the more limited uid specified in the xattr. * or the more limited uid specified in the xattr.
*/ */
rootkuid = mapped_kuid_fs(mnt_userns, fs_ns, rootkuid); if (!rootid_owns_currentns(rootvfsuid))
if (!rootid_owns_currentns(rootkuid))
return -ENODATA; return -ENODATA;
CAP_FOR_EACH_U32(i) { CAP_FOR_EACH_U32(i) {
...@@ -716,7 +717,7 @@ int get_vfs_caps_from_disk(struct user_namespace *mnt_userns, ...@@ -716,7 +717,7 @@ int get_vfs_caps_from_disk(struct user_namespace *mnt_userns,
cpu_caps->permitted.cap[CAP_LAST_U32] &= CAP_LAST_U32_VALID_MASK; cpu_caps->permitted.cap[CAP_LAST_U32] &= CAP_LAST_U32_VALID_MASK;
cpu_caps->inheritable.cap[CAP_LAST_U32] &= CAP_LAST_U32_VALID_MASK; cpu_caps->inheritable.cap[CAP_LAST_U32] &= CAP_LAST_U32_VALID_MASK;
cpu_caps->rootid = rootkuid; cpu_caps->rootid = vfsuid_into_kuid(rootvfsuid);
return 0; return 0;
} }
......
...@@ -85,8 +85,8 @@ struct ima_rule_entry { ...@@ -85,8 +85,8 @@ struct ima_rule_entry {
kgid_t fgroup; kgid_t fgroup;
bool (*uid_op)(kuid_t cred_uid, kuid_t rule_uid); /* Handlers for operators */ bool (*uid_op)(kuid_t cred_uid, kuid_t rule_uid); /* Handlers for operators */
bool (*gid_op)(kgid_t cred_gid, kgid_t rule_gid); bool (*gid_op)(kgid_t cred_gid, kgid_t rule_gid);
bool (*fowner_op)(kuid_t cred_uid, kuid_t rule_uid); /* uid_eq(), uid_gt(), uid_lt() */ bool (*fowner_op)(vfsuid_t vfsuid, kuid_t rule_uid); /* vfsuid_eq_kuid(), vfsuid_gt_kuid(), vfsuid_lt_kuid() */
bool (*fgroup_op)(kgid_t cred_gid, kgid_t rule_gid); /* gid_eq(), gid_gt(), gid_lt() */ bool (*fgroup_op)(vfsgid_t vfsgid, kgid_t rule_gid); /* vfsgid_eq_kgid(), vfsgid_gt_kgid(), vfsgid_lt_kgid() */
int pcr; int pcr;
unsigned int allowed_algos; /* bitfield of allowed hash algorithms */ unsigned int allowed_algos; /* bitfield of allowed hash algorithms */
struct { struct {
...@@ -186,11 +186,11 @@ static struct ima_rule_entry default_appraise_rules[] __ro_after_init = { ...@@ -186,11 +186,11 @@ static struct ima_rule_entry default_appraise_rules[] __ro_after_init = {
.flags = IMA_FUNC | IMA_DIGSIG_REQUIRED}, .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED},
#endif #endif
#ifndef CONFIG_IMA_APPRAISE_SIGNED_INIT #ifndef CONFIG_IMA_APPRAISE_SIGNED_INIT
{.action = APPRAISE, .fowner = GLOBAL_ROOT_UID, .fowner_op = &uid_eq, {.action = APPRAISE, .fowner = GLOBAL_ROOT_UID, .fowner_op = &vfsuid_eq_kuid,
.flags = IMA_FOWNER}, .flags = IMA_FOWNER},
#else #else
/* force signature */ /* force signature */
{.action = APPRAISE, .fowner = GLOBAL_ROOT_UID, .fowner_op = &uid_eq, {.action = APPRAISE, .fowner = GLOBAL_ROOT_UID, .fowner_op = &vfsuid_eq_kuid,
.flags = IMA_FOWNER | IMA_DIGSIG_REQUIRED}, .flags = IMA_FOWNER | IMA_DIGSIG_REQUIRED},
#endif #endif
}; };
...@@ -601,10 +601,12 @@ static bool ima_match_rules(struct ima_rule_entry *rule, ...@@ -601,10 +601,12 @@ static bool ima_match_rules(struct ima_rule_entry *rule,
return false; return false;
} }
if ((rule->flags & IMA_FOWNER) && if ((rule->flags & IMA_FOWNER) &&
!rule->fowner_op(i_uid_into_mnt(mnt_userns, inode), rule->fowner)) !rule->fowner_op(i_uid_into_vfsuid(mnt_userns, inode),
rule->fowner))
return false; return false;
if ((rule->flags & IMA_FGROUP) && if ((rule->flags & IMA_FGROUP) &&
!rule->fgroup_op(i_gid_into_mnt(mnt_userns, inode), rule->fgroup)) !rule->fgroup_op(i_gid_into_vfsgid(mnt_userns, inode),
rule->fgroup))
return false; return false;
for (i = 0; i < MAX_LSM_RULES; i++) { for (i = 0; i < MAX_LSM_RULES; i++) {
int rc = 0; int rc = 0;
...@@ -1371,8 +1373,8 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) ...@@ -1371,8 +1373,8 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
entry->fgroup = INVALID_GID; entry->fgroup = INVALID_GID;
entry->uid_op = &uid_eq; entry->uid_op = &uid_eq;
entry->gid_op = &gid_eq; entry->gid_op = &gid_eq;
entry->fowner_op = &uid_eq; entry->fowner_op = &vfsuid_eq_kuid;
entry->fgroup_op = &gid_eq; entry->fgroup_op = &vfsgid_eq_kgid;
entry->action = UNKNOWN; entry->action = UNKNOWN;
while ((p = strsep(&rule, " \t")) != NULL) { while ((p = strsep(&rule, " \t")) != NULL) {
substring_t args[MAX_OPT_ARGS]; substring_t args[MAX_OPT_ARGS];
...@@ -1650,11 +1652,11 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) ...@@ -1650,11 +1652,11 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
} }
break; break;
case Opt_fowner_gt: case Opt_fowner_gt:
entry->fowner_op = &uid_gt; entry->fowner_op = &vfsuid_gt_kuid;
fallthrough; fallthrough;
case Opt_fowner_lt: case Opt_fowner_lt:
if (token == Opt_fowner_lt) if (token == Opt_fowner_lt)
entry->fowner_op = &uid_lt; entry->fowner_op = &vfsuid_lt_kuid;
fallthrough; fallthrough;
case Opt_fowner_eq: case Opt_fowner_eq:
ima_log_string_op(ab, "fowner", args[0].from, token); ima_log_string_op(ab, "fowner", args[0].from, token);
...@@ -1676,11 +1678,11 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) ...@@ -1676,11 +1678,11 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
} }
break; break;
case Opt_fgroup_gt: case Opt_fgroup_gt:
entry->fgroup_op = &gid_gt; entry->fgroup_op = &vfsgid_gt_kgid;
fallthrough; fallthrough;
case Opt_fgroup_lt: case Opt_fgroup_lt:
if (token == Opt_fgroup_lt) if (token == Opt_fgroup_lt)
entry->fgroup_op = &gid_lt; entry->fgroup_op = &vfsgid_lt_kgid;
fallthrough; fallthrough;
case Opt_fgroup_eq: case Opt_fgroup_eq:
ima_log_string_op(ab, "fgroup", args[0].from, token); ima_log_string_op(ab, "fgroup", args[0].from, token);
...@@ -2151,9 +2153,9 @@ int ima_policy_show(struct seq_file *m, void *v) ...@@ -2151,9 +2153,9 @@ int ima_policy_show(struct seq_file *m, void *v)
if (entry->flags & IMA_FOWNER) { if (entry->flags & IMA_FOWNER) {
snprintf(tbuf, sizeof(tbuf), "%d", __kuid_val(entry->fowner)); snprintf(tbuf, sizeof(tbuf), "%d", __kuid_val(entry->fowner));
if (entry->fowner_op == &uid_gt) if (entry->fowner_op == &vfsuid_gt_kuid)
seq_printf(m, pt(Opt_fowner_gt), tbuf); seq_printf(m, pt(Opt_fowner_gt), tbuf);
else if (entry->fowner_op == &uid_lt) else if (entry->fowner_op == &vfsuid_lt_kuid)
seq_printf(m, pt(Opt_fowner_lt), tbuf); seq_printf(m, pt(Opt_fowner_lt), tbuf);
else else
seq_printf(m, pt(Opt_fowner_eq), tbuf); seq_printf(m, pt(Opt_fowner_eq), tbuf);
...@@ -2162,9 +2164,9 @@ int ima_policy_show(struct seq_file *m, void *v) ...@@ -2162,9 +2164,9 @@ int ima_policy_show(struct seq_file *m, void *v)
if (entry->flags & IMA_FGROUP) { if (entry->flags & IMA_FGROUP) {
snprintf(tbuf, sizeof(tbuf), "%d", __kgid_val(entry->fgroup)); snprintf(tbuf, sizeof(tbuf), "%d", __kgid_val(entry->fgroup));
if (entry->fgroup_op == &gid_gt) if (entry->fgroup_op == &vfsgid_gt_kgid)
seq_printf(m, pt(Opt_fgroup_gt), tbuf); seq_printf(m, pt(Opt_fgroup_gt), tbuf);
else if (entry->fgroup_op == &gid_lt) else if (entry->fgroup_op == &vfsgid_lt_kgid)
seq_printf(m, pt(Opt_fgroup_lt), tbuf); seq_printf(m, pt(Opt_fgroup_lt), tbuf);
else else
seq_printf(m, pt(Opt_fgroup_eq), tbuf); seq_printf(m, pt(Opt_fgroup_eq), tbuf);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment