]> Git Repo - linux.git/commitdiff
Merge tag 'lsm-pr-20231030' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/lsm
authorLinus Torvalds <[email protected]>
Tue, 31 Oct 2023 06:13:17 +0000 (20:13 -1000)
committerLinus Torvalds <[email protected]>
Tue, 31 Oct 2023 06:13:17 +0000 (20:13 -1000)
Pull LSM updates from Paul Moore:

 - Add new credential functions, get_cred_many() and put_cred_many() to
   save some atomic_t operations for a few operations.

   While not strictly LSM related, this patchset had been rotting on the
   mailing lists for some time and since the LSMs do care a lot about
   credentials I thought it reasonable to give this patch a home.

 - Five patches to constify different LSM hook parameters.

 - Fix a spelling mistake.

* tag 'lsm-pr-20231030' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/lsm:
  lsm: fix a spelling mistake
  cred: add get_cred_many and put_cred_many
  lsm: constify 'sb' parameter in security_sb_kern_mount()
  lsm: constify 'bprm' parameter in security_bprm_committed_creds()
  lsm: constify 'bprm' parameter in security_bprm_committing_creds()
  lsm: constify 'file' parameter in security_bprm_creds_from_file()
  lsm: constify 'sb' parameter in security_quotactl()

1  2 
include/linux/cred.h
include/linux/fs.h
kernel/cred.c
security/selinux/hooks.c

diff --combined include/linux/cred.h
index 92f8d772da6fd51507ae3a2141ad79ee864914da,56bc432fe49bf1612120f1b1d0f7acb3a9f9992f..af8d353a4b86af3d4e571301238a4e6aa20b78f9
@@@ -12,7 -12,6 +12,7 @@@
  #include <linux/init.h>
  #include <linux/key.h>
  #include <linux/atomic.h>
 +#include <linux/refcount.h>
  #include <linux/uidgid.h>
  #include <linux/sched.h>
  #include <linux/sched/user.h>
@@@ -24,7 -23,7 +24,7 @@@ struct inode
   * COW Supplementary groups list
   */
  struct group_info {
 -      atomic_t        usage;
 +      refcount_t      usage;
        int             ngroups;
        kgid_t          gid[];
  } __randomize_layout;
@@@ -40,7 -39,7 +40,7 @@@
   */
  static inline struct group_info *get_group_info(struct group_info *gi)
  {
 -      atomic_inc(&gi->usage);
 +      refcount_inc(&gi->usage);
        return gi;
  }
  
@@@ -50,7 -49,7 +50,7 @@@
   */
  #define put_group_info(group_info)                    \
  do {                                                  \
 -      if (atomic_dec_and_test(&(group_info)->usage))  \
 +      if (refcount_dec_and_test(&(group_info)->usage))        \
                groups_free(group_info);                \
  } while (0)
  
@@@ -219,6 -218,20 +219,20 @@@ static inline bool cap_ambient_invarian
                                          cred->cap_inheritable));
  }
  
+ /**
+  * get_new_cred_many - Get references on a new set of credentials
+  * @cred: The new credentials to reference
+  * @nr: Number of references to acquire
+  *
+  * Get references on the specified set of new credentials.  The caller must
+  * release all acquired references.
+  */
+ static inline struct cred *get_new_cred_many(struct cred *cred, int nr)
+ {
+       atomic_add(nr, &cred->usage);
+       return cred;
+ }
  /**
   * get_new_cred - Get a reference on a new set of credentials
   * @cred: The new credentials to reference
   */
  static inline struct cred *get_new_cred(struct cred *cred)
  {
-       atomic_inc(&cred->usage);
-       return cred;
+       return get_new_cred_many(cred, 1);
  }
  
  /**
-  * get_cred - Get a reference on a set of credentials
+  * get_cred_many - Get references on a set of credentials
   * @cred: The credentials to reference
+  * @nr: Number of references to acquire
   *
-  * Get a reference on the specified set of credentials.  The caller must
-  * release the reference.  If %NULL is passed, it is returned with no action.
+  * Get references on the specified set of credentials.  The caller must release
+  * all acquired reference.  If %NULL is passed, it is returned with no action.
   *
   * This is used to deal with a committed set of credentials.  Although the
   * pointer is const, this will temporarily discard the const and increment the
   * accidental alteration of a set of credentials that should be considered
   * immutable.
   */
- static inline const struct cred *get_cred(const struct cred *cred)
+ static inline const struct cred *get_cred_many(const struct cred *cred, int nr)
  {
        struct cred *nonconst_cred = (struct cred *) cred;
        if (!cred)
                return cred;
        validate_creds(cred);
        nonconst_cred->non_rcu = 0;
-       return get_new_cred(nonconst_cred);
+       return get_new_cred_many(nonconst_cred, nr);
+ }
+ /*
+  * get_cred - Get a reference on a set of credentials
+  * @cred: The credentials to reference
+  *
+  * Get a reference on the specified set of credentials.  The caller must
+  * release the reference.  If %NULL is passed, it is returned with no action.
+  *
+  * This is used to deal with a committed set of credentials.
+  */
+ static inline const struct cred *get_cred(const struct cred *cred)
+ {
+       return get_cred_many(cred, 1);
  }
  
  static inline const struct cred *get_cred_rcu(const struct cred *cred)
  /**
   * put_cred - Release a reference to a set of credentials
   * @cred: The credentials to release
+  * @nr: Number of references to release
   *
   * Release a reference to a set of credentials, deleting them when the last ref
   * is released.  If %NULL is passed, nothing is done.
   * on task_struct are attached by const pointers to prevent accidental
   * alteration of otherwise immutable credential sets.
   */
- static inline void put_cred(const struct cred *_cred)
+ static inline void put_cred_many(const struct cred *_cred, int nr)
  {
        struct cred *cred = (struct cred *) _cred;
  
        if (cred) {
                validate_creds(cred);
-               if (atomic_dec_and_test(&(cred)->usage))
+               if (atomic_sub_and_test(nr, &cred->usage))
                        __put_cred(cred);
        }
  }
  
+ /*
+  * put_cred - Release a reference to a set of credentials
+  * @cred: The credentials to release
+  *
+  * Release a reference to a set of credentials, deleting them when the last ref
+  * is released.  If %NULL is passed, nothing is done.
+  */
+ static inline void put_cred(const struct cred *cred)
+ {
+       put_cred_many(cred, 1);
+ }
  /**
   * current_cred - Access the current task's subjective credentials
   *
diff --combined include/linux/fs.h
index bd522c0ac267cdb465f2b1cb8128b9dd776ca096,f69d085e531fbca753a6d940c4dde2b96e955b49..c27c324ba58ac0a90aecc945b25bc14d992d4625
@@@ -67,7 -67,7 +67,7 @@@ struct swap_info_struct
  struct seq_file;
  struct workqueue_struct;
  struct iov_iter;
 -struct fscrypt_info;
 +struct fscrypt_inode_info;
  struct fscrypt_operations;
  struct fsverity_info;
  struct fsverity_operations;
@@@ -671,8 -671,8 +671,8 @@@ struct inode 
        };
        dev_t                   i_rdev;
        loff_t                  i_size;
 -      struct timespec64       i_atime;
 -      struct timespec64       i_mtime;
 +      struct timespec64       __i_atime;
 +      struct timespec64       __i_mtime;
        struct timespec64       __i_ctime; /* use inode_*_ctime accessors! */
        spinlock_t              i_lock; /* i_blocks, i_bytes, maybe i_size */
        unsigned short          i_bytes;
  #endif
  
  #ifdef CONFIG_FS_ENCRYPTION
 -      struct fscrypt_info     *i_crypt_info;
 +      struct fscrypt_inode_info       *i_crypt_info;
  #endif
  
  #ifdef CONFIG_FS_VERITY
@@@ -1042,10 -1042,7 +1042,10 @@@ static inline struct file *get_file(str
        atomic_long_inc(&f->f_count);
        return f;
  }
 -#define get_file_rcu(x) atomic_long_inc_not_zero(&(x)->f_count)
 +
 +struct file *get_file_rcu(struct file __rcu **f);
 +struct file *get_file_active(struct file **f);
 +
  #define file_count(x) atomic_long_read(&(x)->f_count)
  
  #define       MAX_NON_LFS     ((1UL<<31) - 1)
@@@ -1122,7 -1119,7 +1122,7 @@@ extern int send_sigurg(struct fown_stru
  #define SB_NOATIME      BIT(10)       /* Do not update access times. */
  #define SB_NODIRATIME   BIT(11)       /* Do not update directory access times */
  #define SB_SILENT       BIT(15)
 -#define SB_POSIXACL     BIT(16)       /* VFS does not apply the umask */
 +#define SB_POSIXACL     BIT(16)       /* Supports POSIX ACLs */
  #define SB_INLINECRYPT  BIT(17)       /* Use blk-crypto for encrypted files */
  #define SB_KERNMOUNT    BIT(22)       /* this is a kern_mount call */
  #define SB_I_VERSION    BIT(23)       /* Update inode I_version field */
  #define SB_I_PERSB_BDI        0x00000200      /* has a per-sb bdi */
  #define SB_I_TS_EXPIRY_WARNED 0x00000400 /* warned about timestamp range expiry */
  #define SB_I_RETIRED  0x00000800      /* superblock shouldn't be reused */
 +#define SB_I_NOUMASK  0x00001000      /* VFS does not apply umask */
  
  /* Possible states of 'frozen' field */
  enum {
@@@ -1210,7 -1206,7 +1210,7 @@@ struct super_block 
  #ifdef CONFIG_SECURITY
        void                    *s_security;
  #endif
 -      const struct xattr_handler **s_xattr;
 +      const struct xattr_handler * const *s_xattr;
  #ifdef CONFIG_FS_ENCRYPTION
        const struct fscrypt_operations *s_cop;
        struct fscrypt_keyring  *s_master_keys; /* master crypto keys in use */
        struct hlist_bl_head    s_roots;        /* alternate root dentries for NFS */
        struct list_head        s_mounts;       /* list of mounts; _not_ for fs use */
        struct block_device     *s_bdev;
 +      struct bdev_handle      *s_bdev_handle;
        struct backing_dev_info *s_bdi;
        struct mtd_info         *s_mtd;
        struct hlist_node       s_instances;
@@@ -1513,84 -1508,56 +1513,84 @@@ static inline bool fsuidgid_has_mapping
               kgid_has_mapping(fs_userns, kgid);
  }
  
 -struct timespec64 current_mgtime(struct inode *inode);
  struct timespec64 current_time(struct inode *inode);
  struct timespec64 inode_set_ctime_current(struct inode *inode);
  
 -/*
 - * Multigrain timestamps
 - *
 - * Conditionally use fine-grained ctime and mtime timestamps when there
 - * are users actively observing them via getattr. The primary use-case
 - * for this is NFS clients that use the ctime to distinguish between
 - * different states of the file, and that are often fooled by multiple
 - * operations that occur in the same coarse-grained timer tick.
 - *
 - * The kernel always keeps normalized struct timespec64 values in the ctime,
 - * which means that only the first 30 bits of the value are used. Use the
 - * 31st bit of the ctime's tv_nsec field as a flag to indicate that the value
 - * has been queried since it was last updated.
 - */
 -#define I_CTIME_QUERIED               (1L<<30)
 +static inline time64_t inode_get_atime_sec(const struct inode *inode)
 +{
 +      return inode->__i_atime.tv_sec;
 +}
  
 -/**
 - * inode_get_ctime - fetch the current ctime from the inode
 - * @inode: inode from which to fetch ctime
 - *
 - * Grab the current ctime tv_nsec field from the inode, mask off the
 - * I_CTIME_QUERIED flag and return it. This is mostly intended for use by
 - * internal consumers of the ctime that aren't concerned with ensuring a
 - * fine-grained update on the next change (e.g. when preparing to store
 - * the value in the backing store for later retrieval).
 - *
 - * This is safe to call regardless of whether the underlying filesystem
 - * is using multigrain timestamps.
 - */
 -static inline struct timespec64 inode_get_ctime(const struct inode *inode)
 +static inline long inode_get_atime_nsec(const struct inode *inode)
 +{
 +      return inode->__i_atime.tv_nsec;
 +}
 +
 +static inline struct timespec64 inode_get_atime(const struct inode *inode)
 +{
 +      return inode->__i_atime;
 +}
 +
 +static inline struct timespec64 inode_set_atime_to_ts(struct inode *inode,
 +                                                    struct timespec64 ts)
  {
 -      struct timespec64 ctime;
 +      inode->__i_atime = ts;
 +      return ts;
 +}
 +
 +static inline struct timespec64 inode_set_atime(struct inode *inode,
 +                                              time64_t sec, long nsec)
 +{
 +      struct timespec64 ts = { .tv_sec  = sec,
 +                               .tv_nsec = nsec };
 +      return inode_set_atime_to_ts(inode, ts);
 +}
  
 -      ctime.tv_sec = inode->__i_ctime.tv_sec;
 -      ctime.tv_nsec = inode->__i_ctime.tv_nsec & ~I_CTIME_QUERIED;
 +static inline time64_t inode_get_mtime_sec(const struct inode *inode)
 +{
 +      return inode->__i_mtime.tv_sec;
 +}
  
 -      return ctime;
 +static inline long inode_get_mtime_nsec(const struct inode *inode)
 +{
 +      return inode->__i_mtime.tv_nsec;
 +}
 +
 +static inline struct timespec64 inode_get_mtime(const struct inode *inode)
 +{
 +      return inode->__i_mtime;
 +}
 +
 +static inline struct timespec64 inode_set_mtime_to_ts(struct inode *inode,
 +                                                    struct timespec64 ts)
 +{
 +      inode->__i_mtime = ts;
 +      return ts;
 +}
 +
 +static inline struct timespec64 inode_set_mtime(struct inode *inode,
 +                                              time64_t sec, long nsec)
 +{
 +      struct timespec64 ts = { .tv_sec  = sec,
 +                               .tv_nsec = nsec };
 +      return inode_set_mtime_to_ts(inode, ts);
 +}
 +
 +static inline time64_t inode_get_ctime_sec(const struct inode *inode)
 +{
 +      return inode->__i_ctime.tv_sec;
 +}
 +
 +static inline long inode_get_ctime_nsec(const struct inode *inode)
 +{
 +      return inode->__i_ctime.tv_nsec;
 +}
 +
 +static inline struct timespec64 inode_get_ctime(const struct inode *inode)
 +{
 +      return inode->__i_ctime;
  }
  
 -/**
 - * inode_set_ctime_to_ts - set the ctime in the inode
 - * @inode: inode in which to set the ctime
 - * @ts: value to set in the ctime field
 - *
 - * Set the ctime in @inode to @ts
 - */
  static inline struct timespec64 inode_set_ctime_to_ts(struct inode *inode,
                                                      struct timespec64 ts)
  {
@@@ -1615,8 -1582,6 +1615,8 @@@ static inline struct timespec64 inode_s
        return inode_set_ctime_to_ts(inode, ts);
  }
  
 +struct timespec64 simple_inode_init_ts(struct inode *inode);
 +
  /*
   * Snapshotting support.
   */
@@@ -2145,12 -2110,7 +2145,12 @@@ static inline bool sb_rdonly(const stru
  #define IS_NOQUOTA(inode)     ((inode)->i_flags & S_NOQUOTA)
  #define IS_APPEND(inode)      ((inode)->i_flags & S_APPEND)
  #define IS_IMMUTABLE(inode)   ((inode)->i_flags & S_IMMUTABLE)
 +
 +#ifdef CONFIG_FS_POSIX_ACL
  #define IS_POSIXACL(inode)    __IS_FLG(inode, SB_POSIXACL)
 +#else
 +#define IS_POSIXACL(inode)    0
 +#endif
  
  #define IS_DEADDIR(inode)     ((inode)->i_flags & S_DEAD)
  #define IS_NOCMTIME(inode)    ((inode)->i_flags & S_NOCMTIME)
@@@ -2374,6 -2334,7 +2374,6 @@@ struct file_system_type 
  #define FS_USERNS_MOUNT               8       /* Can be mounted by userns root */
  #define FS_DISALLOW_NOTIFY_PERM       16      /* Disable fanotify permission events */
  #define FS_ALLOW_IDMAP         32      /* FS has been updated to handle vfs idmappings. */
 -#define FS_MGTIME             64      /* FS uses multigrain timestamps */
  #define FS_RENAME_DOES_D_MOVE 32768   /* FS will handle d_move() during rename() internally. */
        int (*init_fs_context)(struct fs_context *);
        const struct fs_parameter_spec *parameters;
  
  #define MODULE_ALIAS_FS(NAME) MODULE_ALIAS("fs-" NAME)
  
 -/**
 - * is_mgtime: is this inode using multigrain timestamps
 - * @inode: inode to test for multigrain timestamps
 - *
 - * Return true if the inode uses multigrain timestamps, false otherwise.
 - */
 -static inline bool is_mgtime(const struct inode *inode)
 -{
 -      return inode->i_sb->s_type->fs_flags & FS_MGTIME;
 -}
 -
  extern struct dentry *mount_bdev(struct file_system_type *fs_type,
        int flags, const char *dev_name, void *data,
        int (*fill_super)(struct super_block *, void *, int));
@@@ -2472,13 -2444,13 +2472,13 @@@ struct audit_names
  struct filename {
        const char              *name;  /* pointer to actual string */
        const __user char       *uptr;  /* original userland pointer */
 -      int                     refcnt;
 +      atomic_t                refcnt;
        struct audit_names      *aname;
        const char              iname[];
  };
  static_assert(offsetof(struct filename, iname) % sizeof(long) == 0);
  
- static inline struct mnt_idmap *file_mnt_idmap(struct file *file)
+ static inline struct mnt_idmap *file_mnt_idmap(const struct file *file)
  {
        return mnt_idmap(file->f_path.mnt);
  }
@@@ -2517,24 -2489,24 +2517,24 @@@ struct file *dentry_open(const struct p
                         const struct cred *creds);
  struct file *dentry_create(const struct path *path, int flags, umode_t mode,
                           const struct cred *cred);
 -struct file *backing_file_open(const struct path *path, int flags,
 +struct file *backing_file_open(const struct path *user_path, int flags,
                               const struct path *real_path,
                               const struct cred *cred);
 -struct path *backing_file_real_path(struct file *f);
 +struct path *backing_file_user_path(struct file *f);
  
  /*
 - * file_real_path - get the path corresponding to f_inode
 + * file_user_path - get the path to display for memory mapped file
   *
 - * When opening a backing file for a stackable filesystem (e.g.,
 - * overlayfs) f_path may be on the stackable filesystem and f_inode on
 - * the underlying filesystem.  When the path associated with f_inode is
 - * needed, this helper should be used instead of accessing f_path
 - * directly.
 -*/
 -static inline const struct path *file_real_path(struct file *f)
 + * When mmapping a file on a stackable filesystem (e.g., overlayfs), the file
 + * stored in ->vm_file is a backing file whose f_inode is on the underlying
 + * filesystem.  When the mapped file path is displayed to user (e.g. via
 + * /proc/<pid>/maps), this helper should be used to get the path to display
 + * to the user, which is the path of the fd that user has requested to map.
 + */
 +static inline const struct path *file_user_path(struct file *f)
  {
        if (unlikely(f->f_mode & FMODE_BACKING))
 -              return backing_file_real_path(f);
 +              return backing_file_user_path(f);
        return &f->f_path;
  }
  
@@@ -3082,6 -3054,7 +3082,6 @@@ extern void page_put_link(void *)
  extern int page_symlink(struct inode *inode, const char *symname, int len);
  extern const struct inode_operations page_symlink_inode_operations;
  extern void kfree_link(void *);
 -void fill_mg_cmtime(struct kstat *stat, u32 request_mask, struct inode *inode);
  void generic_fillattr(struct mnt_idmap *, u32, struct inode *, struct kstat *);
  void generic_fill_statx_attr(struct inode *inode, struct kstat *stat);
  extern int vfs_getattr_nosec(const struct path *, struct kstat *, u32, unsigned int);
diff --combined kernel/cred.c
index 4dc0b27b546250f65891084b846ad314dac77667,9398e534b997b8370012bfac7ff3893bba0f102a..3c714cb31660d970cb7d19cd25b48161cf50a6df
@@@ -36,7 -36,7 +36,7 @@@ do {                                                                  
  static struct kmem_cache *cred_jar;
  
  /* init to 2 - one for init_task, one to ensure it is never freed */
 -static struct group_info init_groups = { .usage = ATOMIC_INIT(2) };
 +static struct group_info init_groups = { .usage = REFCOUNT_INIT(2) };
  
  /*
   * The initial credentials for the initial task
@@@ -162,23 -162,29 +162,29 @@@ EXPORT_SYMBOL(__put_cred)
   */
  void exit_creds(struct task_struct *tsk)
  {
-       struct cred *cred;
+       struct cred *real_cred, *cred;
  
        kdebug("exit_creds(%u,%p,%p,{%d,%d})", tsk->pid, tsk->real_cred, tsk->cred,
               atomic_read(&tsk->cred->usage),
               read_cred_subscribers(tsk->cred));
  
-       cred = (struct cred *) tsk->real_cred;
+       real_cred = (struct cred *) tsk->real_cred;
        tsk->real_cred = NULL;
-       validate_creds(cred);
-       alter_cred_subscribers(cred, -1);
-       put_cred(cred);
  
        cred = (struct cred *) tsk->cred;
        tsk->cred = NULL;
        validate_creds(cred);
-       alter_cred_subscribers(cred, -1);
-       put_cred(cred);
+       if (real_cred == cred) {
+               alter_cred_subscribers(cred, -2);
+               put_cred_many(cred, 2);
+       } else {
+               validate_creds(real_cred);
+               alter_cred_subscribers(real_cred, -1);
+               put_cred(real_cred);
+               alter_cred_subscribers(cred, -1);
+               put_cred(cred);
+       }
  
  #ifdef CONFIG_KEYS_REQUEST_CACHE
        key_put(tsk->cached_requested_key);
@@@ -355,8 -361,7 +361,7 @@@ int copy_creds(struct task_struct *p, u
  #endif
                clone_flags & CLONE_THREAD
            ) {
-               p->real_cred = get_cred(p->cred);
-               get_cred(p->cred);
+               p->real_cred = get_cred_many(p->cred, 2);
                alter_cred_subscribers(p->cred, 2);
                kdebug("share_creds(%p{%d,%d})",
                       p->cred, atomic_read(&p->cred->usage),
@@@ -520,8 -525,7 +525,7 @@@ int commit_creds(struct cred *new
                proc_id_connector(task, PROC_EVENT_GID);
  
        /* release the old obj and subj refs both */
-       put_cred(old);
-       put_cred(old);
+       put_cred_many(old, 2);
        return 0;
  }
  EXPORT_SYMBOL(commit_creds);
diff --combined security/selinux/hooks.c
index 2aa0e219d72177799b915322d73e0af1698901f6,195db92ac99c2481d857ee8ee2369efc175863ee..feda711c6b7b84c19099568b96b3b5cbf121886d
@@@ -1937,7 -1937,7 +1937,7 @@@ static inline int may_rename(struct ino
  
  /* Check whether a task can perform a filesystem operation. */
  static int superblock_has_perm(const struct cred *cred,
-                              struct super_block *sb,
+                              const struct super_block *sb,
                               u32 perms,
                               struct common_audit_data *ad)
  {
@@@ -2139,7 -2139,7 +2139,7 @@@ static int selinux_capable(const struc
        return cred_has_capability(cred, cap, opts, ns == &init_user_ns);
  }
  
- static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
+ static int selinux_quotactl(int cmds, int type, int id, const struct super_block *sb)
  {
        const struct cred *cred = current_cred();
        int rc = 0;
@@@ -2455,7 -2455,7 +2455,7 @@@ static inline void flush_unauthorized_f
  /*
   * Prepare a process for imminent new credential changes due to exec
   */
- static void selinux_bprm_committing_creds(struct linux_binprm *bprm)
+ static void selinux_bprm_committing_creds(const struct linux_binprm *bprm)
  {
        struct task_security_struct *new_tsec;
        struct rlimit *rlim, *initrlim;
   * Clean up the process immediately after the installation of new credentials
   * due to exec
   */
- static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
+ static void selinux_bprm_committed_creds(const struct linux_binprm *bprm)
  {
        const struct task_security_struct *tsec = selinux_cred(current_cred());
        u32 osid, sid;
@@@ -2721,7 -2721,7 +2721,7 @@@ out_bad_option
        return -EINVAL;
  }
  
- static int selinux_sb_kern_mount(struct super_block *sb)
+ static int selinux_sb_kern_mount(const struct super_block *sb)
  {
        const struct cred *cred = current_cred();
        struct common_audit_data ad;
@@@ -2775,20 -2775,14 +2775,20 @@@ static int selinux_umount(struct vfsmou
  static int selinux_fs_context_submount(struct fs_context *fc,
                                   struct super_block *reference)
  {
 -      const struct superblock_security_struct *sbsec;
 +      const struct superblock_security_struct *sbsec = selinux_superblock(reference);
        struct selinux_mnt_opts *opts;
  
 +      /*
 +       * Ensure that fc->security remains NULL when no options are set
 +       * as expected by selinux_set_mnt_opts().
 +       */
 +      if (!(sbsec->flags & (FSCONTEXT_MNT|CONTEXT_MNT|DEFCONTEXT_MNT)))
 +              return 0;
 +
        opts = kzalloc(sizeof(*opts), GFP_KERNEL);
        if (!opts)
                return -ENOMEM;
  
 -      sbsec = selinux_superblock(reference);
        if (sbsec->flags & FSCONTEXT_MNT)
                opts->fscontext_sid = sbsec->sid;
        if (sbsec->flags & CONTEXT_MNT)
This page took 0.090728 seconds and 4 git commands to generate.