On 10/14/2015 5:42 AM, Lukasz Pawelczyk wrote: > This commit uses all the changes introduced in "namespace groundwork" > and previous preparation patches and makes smack aware of its namespace > and mapped labels. > > It modifies the following functions to be namespace aware: > - smk_access > - smk_find_label_name > - smk_get_label > > And all functions that use them (e.g. smk_tskacc). > > It also adds another function that is used throughout Smack LSM hooks: > - smk_labels_valid - it checks whether both, subject and object labels > are properly mapped in a namespace where they are to be used. This > function is used mostly together with a capability check when there is > no proper access check that usually checks for that. > > All the Smack LSM hooks have been adapted to be namespace aware. > > The capabilities (CAP_MAC_ADMIN, CAP_MAC_OVERRIDE) has been allowed in > the namespace for few cases. Check the documentation for the details. > > Signed-off-by: Lukasz Pawelczyk <l.pawelczyk@xxxxxxxxxxx> > Reviewed-by: Casey Schaufler <casey@xxxxxxxxxxxxxxxx> Acked-by: Casey Schaufler <casey@xxxxxxxxxxxxxxxx> > --- > security/smack/smack.h | 29 +++- > security/smack/smack_access.c | 109 ++++++++++-- > security/smack/smack_lsm.c | 390 ++++++++++++++++++++++++++++++------------ > security/smack/smack_ns.c | 39 +++++ > security/smack/smackfs.c | 63 ++++--- > 5 files changed, 483 insertions(+), 147 deletions(-) > > diff --git a/security/smack/smack.h b/security/smack/smack.h > index 4b7489f..3d432f4 100644 > --- a/security/smack/smack.h > +++ b/security/smack/smack.h > @@ -119,6 +119,7 @@ struct superblock_smack { > struct smack_known *smk_floor; > struct smack_known *smk_hat; > struct smack_known *smk_default; > + struct user_namespace *smk_ns; > int smk_initialized; > }; > > @@ -126,6 +127,7 @@ struct socket_smack { > struct smack_known *smk_out; /* outbound label */ > struct smack_known *smk_in; /* inbound label */ > struct smack_known *smk_packet; /* TCP peer label */ > + struct user_namespace *smk_ns; /* user namespace */ > }; > > /* > @@ -146,6 +148,14 @@ struct task_smack { > struct mutex smk_rules_lock; /* lock for the rules */ > }; > > +/* > + * Used for IPC objects (sem, shm, etc) > + */ > +struct ipc_smack { > + struct smack_known *smk_known; /* label for access control */ > + struct user_namespace *smk_ns; /* user namespace */ > +}; > + > #define SMK_INODE_INSTANT 0x01 /* inode is instantiated */ > #define SMK_INODE_TRANSMUTE 0x02 /* directory is transmuting */ > #define SMK_INODE_CHANGED 0x04 /* smack was transmuted */ > @@ -319,10 +329,11 @@ struct smk_audit_info { > */ > int smk_access_entry(char *, char *, struct list_head *); > int smk_access(struct smack_known *, struct smack_known *, > - int, struct smk_audit_info *); > + struct user_namespace *, int, struct smk_audit_info *); > int smk_tskacc(struct task_struct *, struct smack_known *, > + struct user_namespace *, u32, struct smk_audit_info *); > +int smk_curacc(struct smack_known *, struct user_namespace *, > u32, struct smk_audit_info *); > -int smk_curacc(struct smack_known *, u32, struct smk_audit_info *); > struct smack_known *smack_from_secid(const u32); > char *smk_parse_smack(const char *string, int len, bool *allocated); > int smk_netlbl_mls(int, char *, struct netlbl_lsm_secattr *, int); > @@ -335,8 +346,9 @@ int smack_has_ns_privilege(struct task_struct *task, > int smack_has_privilege(struct task_struct *task, int cap); > int smack_ns_privileged(struct user_namespace *user_ns, int cap); > int smack_privileged(int cap); > -char *smk_find_label_name(struct smack_known *skp); > -struct smack_known *smk_get_label(const char *string, int len, bool import); > +char *smk_find_label_name(struct smack_known *skp, struct user_namespace *ns); > +struct smack_known *smk_get_label(const char *string, int len, bool import, > + struct user_namespace *ns); > > /* > * These functions are in smack_ns.c > @@ -350,6 +362,15 @@ struct smack_known *smk_find_unmapped(const char *string, int len, > extern const struct seq_operations proc_label_map_seq_operations; > ssize_t proc_label_map_write(struct task_struct *p, const struct cred *f_cred, > void *value, size_t size); > +bool smk_labels_valid(struct smack_known *sbj, struct smack_known *obj, > + struct user_namespace *ns); > +#else > +static inline bool smk_labels_valid(struct smack_known *sbj, > + struct smack_known *obj, > + struct user_namespace *ns) > +{ > + return true; > +} > #endif /* CONFIG_SECURITY_SMACK_NS */ > > /* > diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c > index 17b7e2c..e230948 100644 > --- a/security/smack/smack_access.c > +++ b/security/smack/smack_access.c > @@ -14,6 +14,7 @@ > #include <linux/slab.h> > #include <linux/fs.h> > #include <linux/sched.h> > +#include <linux/user_namespace.h> > #include "smack.h" > > struct smack_known smack_known_huh = { > @@ -113,6 +114,7 @@ int smk_access_entry(char *subject_label, char *object_label, > * smk_access - determine if a subject has a specific access to an object > * @subject: a pointer to the subject's Smack label entry > * @object: a pointer to the object's Smack label entry > + * @ns: user namespace to check against (usually subject's) > * @request: the access requested, in "MAY" format > * @a : a pointer to the audit data > * > @@ -123,10 +125,34 @@ int smk_access_entry(char *subject_label, char *object_label, > * Smack labels are shared on smack_list > */ > int smk_access(struct smack_known *subject, struct smack_known *object, > - int request, struct smk_audit_info *a) > + struct user_namespace *ns, int request, struct smk_audit_info *a) > { > int may = MAY_NOT; > int rc = 0; > + char *subject_label = subject->smk_known; > + char *object_label = object->smk_known; > +#ifdef CONFIG_SECURITY_SMACK_NS > + struct smack_known_ns *sknp; > + struct smack_known_ns *oknp; > + > + /* > + * For the namespaced case we need to check whether the labels > + * are mapped. If not, refuse. If yes check the builtin rules > + * on the mapped label strings so the builtin labels can > + * work properly inside the namespace. > + */ > + if (smk_find_mapped_ns(ns)) { > + sknp = smk_find_mapped(subject, ns); > + oknp = smk_find_mapped(object, ns); > + if (!sknp || !oknp) { > + rc = -EACCES; > + goto out_audit; > + } > + > + subject_label = sknp->smk_mapped; > + object_label = oknp->smk_mapped; > + } > +#endif > > /* > * Hardcoded comparisons. > @@ -134,7 +160,7 @@ int smk_access(struct smack_known *subject, struct smack_known *object, > /* > * A star subject can't access any object. > */ > - if (subject == &smack_known_star) { > + if (subject_label == smack_known_star.smk_known) { > rc = -EACCES; > goto out_audit; > } > @@ -143,18 +169,19 @@ int smk_access(struct smack_known *subject, struct smack_known *object, > * Tasks cannot be assigned the internet label. > * An internet subject can access any object. > */ > - if (object == &smack_known_web || subject == &smack_known_web) > + if (object_label == smack_known_web.smk_known || > + subject_label == smack_known_web.smk_known) > goto out_audit; > /* > * A star object can be accessed by any subject. > */ > - if (object == &smack_known_star) > + if (object_label == smack_known_star.smk_known) > goto out_audit; > /* > * An object can be accessed in any way by a subject > * with the same label. > */ > - if (subject->smk_known == object->smk_known) > + if (subject_label == object_label) > goto out_audit; > /* > * A hat subject can read or lock any object. > @@ -162,9 +189,9 @@ int smk_access(struct smack_known *subject, struct smack_known *object, > */ > if ((request & MAY_ANYREAD) == request || > (request & MAY_LOCK) == request) { > - if (object == &smack_known_floor) > + if (object_label == smack_known_floor.smk_known) > goto out_audit; > - if (subject == &smack_known_hat) > + if (subject_label == smack_known_hat.smk_known) > goto out_audit; > } > > @@ -174,6 +201,7 @@ int smk_access(struct smack_known *subject, struct smack_known *object, > * access (e.g. read is included in readwrite) it's > * good. A negative response from smk_access_entry() > * indicates there is no entry for this pair. > + * For this check we need real, not mapped labels. > */ > rcu_read_lock(); > may = smk_access_entry(subject->smk_known, object->smk_known, > @@ -219,6 +247,7 @@ out_audit: > * smk_tskacc - determine if a task has a specific access to an object > * @tsp: a pointer to the subject's task > * @obj_known: a pointer to the object's label entry > + * @obj_ns: an object's namespace to check the caps against > * @mode: the access requested, in "MAY" format > * @a : common audit data > * > @@ -228,16 +257,18 @@ out_audit: > * to override the rules. > */ > int smk_tskacc(struct task_struct *task, struct smack_known *obj_known, > - u32 mode, struct smk_audit_info *a) > + struct user_namespace *obj_ns, u32 mode, > + struct smk_audit_info *a) > { > struct smack_known *sbj_known = smk_of_task_struct(task); > + struct user_namespace *sbj_ns = ns_of_task_struct(task); > int may; > int rc; > > /* > * Check the global rule list > */ > - rc = smk_access(sbj_known, obj_known, mode, NULL); > + rc = smk_access(sbj_known, obj_known, sbj_ns, mode, NULL); > if (rc >= 0) { > struct task_smack *tsp; > > @@ -261,8 +292,10 @@ int smk_tskacc(struct task_struct *task, struct smack_known *obj_known, > > /* > * Allow for priviliged to override policy. > + * Either in init_ns or when both labels are mapped. > */ > - if (rc != 0 && smack_privileged(CAP_MAC_OVERRIDE)) > + if (rc != 0 && smk_labels_valid(sbj_known, obj_known, sbj_ns) > + && smack_has_ns_privilege(task, obj_ns, CAP_MAC_OVERRIDE)) > rc = 0; > > out_audit: > @@ -277,6 +310,7 @@ out_audit: > /** > * smk_curacc - determine if current has a specific access to an object > * @obj_known: a pointer to the object's Smack label entry > + * @obj_ns: an object's namespace to check the caps against > * @mode: the access requested, in "MAY" format > * @a : common audit data > * > @@ -285,10 +319,10 @@ out_audit: > * non zero otherwise. It allows that current may have the capability > * to override the rules. > */ > -int smk_curacc(struct smack_known *obj_known, > +int smk_curacc(struct smack_known *obj_known, struct user_namespace *obj_ns, > u32 mode, struct smk_audit_info *a) > { > - return smk_tskacc(current, obj_known, mode, a); > + return smk_tskacc(current, obj_known, obj_ns, mode, a); > } > > #ifdef CONFIG_AUDIT > @@ -671,12 +705,13 @@ DEFINE_MUTEX(smack_onlycap_lock); > * > * For a capability in smack related checks to be effective it needs to: > * - be allowed to be privileged by the onlycap rule. > - * - be in the initial user ns > + * - be in the initial user ns or have a filled map in the child ns > */ > static int smack_capability_allowed(struct smack_known *skp, > struct user_namespace *user_ns) > { > struct smack_onlycap *sop; > + struct smack_ns *sns; > > /* > * All kernel tasks are privileged > @@ -684,8 +719,15 @@ static int smack_capability_allowed(struct smack_known *skp, > if (unlikely(current->flags & PF_KTHREAD)) > return 1; > > +#ifdef CONFIG_SECURITY_SMACK_NS > + sns = user_ns->security; > + > + if (user_ns != &init_user_ns && list_empty(&sns->smk_mapped)) > + return 0; > +#else > if (user_ns != &init_user_ns) > return 0; > +#endif /* CONFIG_SECURITY_SMACK_NS */ > > rcu_read_lock(); > if (list_empty(&smack_onlycap_list)) { > @@ -755,14 +797,32 @@ int smack_privileged(int cap) > } > > /** > - * smk_find_label_name - A helper to get a string value of a label > + * smk_find_label_name - A helper to get a string value of either a label or a > + * mapped label when inside a namespace > * @skp: a label we want a string value from > + * @ns: namespace against which we want to get the value > * > * Returns a pointer to a label name or NULL if label name not found. > */ > -char *smk_find_label_name(struct smack_known *skp) > +char *smk_find_label_name(struct smack_known *skp, struct user_namespace *ns) > { > - return skp->smk_known; > + char *name = NULL; > + > +#ifdef CONFIG_SECURITY_SMACK_NS > + struct smack_known_ns *sknp; > + > + if (smk_find_mapped_ns(ns)) { > + sknp = smk_find_mapped(skp, ns); > + if (sknp != NULL) > + name = sknp->smk_mapped; > + } else { > + name = skp->smk_known; > + } > +#else > + name = skp->smk_known; > +#endif > + > + return name; > } > > /** > @@ -771,17 +831,32 @@ char *smk_find_label_name(struct smack_known *skp) > * @string: a name of a label we look for or want to import > * @len: the string size, or zero if it is NULL terminated > * @import: whether we should import the label if not found > + * @ns: a namespace the looked for label should be in > * > * Returns a smack_known label that is either imported or found. > * NULL if label not found (only when import == false). > * Error code otherwise. > */ > -struct smack_known *smk_get_label(const char *string, int len, bool import) > +struct smack_known *smk_get_label(const char *string, int len, bool import, > + struct user_namespace *ns) > { > struct smack_known *skp; > bool allocated; > char *cp; > > +#ifdef CONFIG_SECURITY_SMACK_NS > + if (smk_find_mapped_ns(ns)) { > + skp = smk_find_unmapped(string, len, ns); > + > + /* Label not found but we can't import in namespaces */ > + if (skp == NULL && import) > + skp = ERR_PTR(-EBADR); > + > + /* will also return error codes from smk_find_unmapped() */ > + return skp; > + } > +#endif > + > if (import) { > skp = smk_import_entry(string, len); > } else { > diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c > index 206e0ce..8e0da67 100644 > --- a/security/smack/smack_lsm.c > +++ b/security/smack/smack_lsm.c > @@ -383,6 +383,7 @@ static inline unsigned int smk_ptrace_mode(unsigned int mode) > * smk_ptrace_rule_check - helper for ptrace access > * @tracer: tracer process > * @tracee_known: label entry of the process that's about to be traced > + * @tracee_ns: a tracee's namespace to check the caps against > * @mode: ptrace attachment mode (PTRACE_MODE_*) > * @func: name of the function that called us, used for audit > * > @@ -390,6 +391,7 @@ static inline unsigned int smk_ptrace_mode(unsigned int mode) > */ > static int smk_ptrace_rule_check(struct task_struct *tracer, > struct smack_known *tracee_known, > + struct user_namespace *tracee_ns, > unsigned int mode, const char *func) > { > int rc; > @@ -401,21 +403,28 @@ static int smk_ptrace_rule_check(struct task_struct *tracer, > saip = &ad; > } > > - > if ((mode & PTRACE_MODE_ATTACH) && > (smack_ptrace_rule == SMACK_PTRACE_EXACT || > smack_ptrace_rule == SMACK_PTRACE_DRACONIAN)) { > struct smack_known *tracer_known = smk_of_task_struct(tracer); > + struct user_namespace *tracer_ns = ns_of_task_struct(tracer); > + > + if (!smk_labels_valid(tracer_known, tracee_known, tracer_ns)) { > + rc = -EACCES; > + goto out; > + } > > if (tracer_known->smk_known == tracee_known->smk_known) > rc = 0; > else if (smack_ptrace_rule == SMACK_PTRACE_DRACONIAN) > rc = -EACCES; > - else if (smack_has_privilege(tracer, CAP_SYS_PTRACE)) > + else if (smack_has_ns_privilege(tracer, tracee_ns, > + CAP_SYS_PTRACE)) > rc = 0; > else > rc = -EPERM; > > +out: > if (saip) > smack_log(tracer_known->smk_known, > tracee_known->smk_known, > @@ -425,7 +434,8 @@ static int smk_ptrace_rule_check(struct task_struct *tracer, > } > > /* In case of rule==SMACK_PTRACE_DEFAULT or mode==PTRACE_MODE_READ */ > - return smk_tskacc(tracer, tracee_known, smk_ptrace_mode(mode), saip); > + return smk_tskacc(tracer, tracee_known, tracee_ns, > + smk_ptrace_mode(mode), saip); > } > > /* > @@ -445,8 +455,9 @@ static int smk_ptrace_rule_check(struct task_struct *tracer, > static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode) > { > struct smack_known *skp = smk_of_task_struct(ctp); > + struct user_namespace *ns = ns_of_task_struct(ctp); > > - return smk_ptrace_rule_check(current, skp, mode, __func__); > + return smk_ptrace_rule_check(current, skp, ns, mode, __func__); > } > > /** > @@ -460,8 +471,10 @@ static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode) > static int smack_ptrace_traceme(struct task_struct *ptp) > { > struct smack_known *skp = smk_of_current(); > + struct user_namespace *ns = ns_of_current(); > > - return smk_ptrace_rule_check(ptp, skp, PTRACE_MODE_ATTACH, __func__); > + return smk_ptrace_rule_check(ptp, skp, ns, PTRACE_MODE_ATTACH, > + __func__); > } > > /** > @@ -508,6 +521,7 @@ static int smack_sb_alloc_security(struct super_block *sb) > sbsp->smk_default = &smack_known_floor; > sbsp->smk_floor = &smack_known_floor; > sbsp->smk_hat = &smack_known_hat; > + sbsp->smk_ns = get_user_ns(&init_user_ns); > /* > * smk_initialized will be zero from kzalloc. > */ > @@ -523,6 +537,9 @@ static int smack_sb_alloc_security(struct super_block *sb) > */ > static void smack_sb_free_security(struct super_block *sb) > { > + struct superblock_smack *sbsp = sb->s_security; > + > + put_user_ns(sbsp->smk_ns); > kfree(sb->s_security); > sb->s_security = NULL; > } > @@ -724,6 +741,7 @@ static int smack_set_mnt_opts(struct super_block *sb, > struct smack_known *skp; > int i; > int num_opts = opts->num_mnt_opts; > + struct user_namespace *ns = ns_of_current(); > int transmute = 0; > > if (sp->smk_initialized) > @@ -734,31 +752,31 @@ static int smack_set_mnt_opts(struct super_block *sb, > for (i = 0; i < num_opts; i++) { > switch (opts->mnt_opts_flags[i]) { > case FSDEFAULT_MNT: > - skp = smk_get_label(opts->mnt_opts[i], 0, true); > + skp = smk_get_label(opts->mnt_opts[i], 0, true, ns); > if (IS_ERR(skp)) > return PTR_ERR(skp); > sp->smk_default = skp; > break; > case FSFLOOR_MNT: > - skp = smk_get_label(opts->mnt_opts[i], 0, true); > + skp = smk_get_label(opts->mnt_opts[i], 0, true, ns); > if (IS_ERR(skp)) > return PTR_ERR(skp); > sp->smk_floor = skp; > break; > case FSHAT_MNT: > - skp = smk_get_label(opts->mnt_opts[i], 0, true); > + skp = smk_get_label(opts->mnt_opts[i], 0, true, ns); > if (IS_ERR(skp)) > return PTR_ERR(skp); > sp->smk_hat = skp; > break; > case FSROOT_MNT: > - skp = smk_get_label(opts->mnt_opts[i], 0, true); > + skp = smk_get_label(opts->mnt_opts[i], 0, true, ns); > if (IS_ERR(skp)) > return PTR_ERR(skp); > sp->smk_root = skp; > break; > case FSTRANS_MNT: > - skp = smk_get_label(opts->mnt_opts[i], 0, true); > + skp = smk_get_label(opts->mnt_opts[i], 0, true, ns); > if (IS_ERR(skp)) > return PTR_ERR(skp); > sp->smk_root = skp; > @@ -769,7 +787,12 @@ static int smack_set_mnt_opts(struct super_block *sb, > } > } > > - if (!smack_privileged(CAP_MAC_ADMIN)) { > + /* > + * Check for non-privileged case. If current is inside the namespace > + * and the it has privileges the validity of labels has already been > + * checked during smk_get_label() > + */ > + if (!smack_ns_privileged(ns, CAP_MAC_ADMIN)) { > /* > * Unprivileged mounts don't get to specify Smack values. > */ > @@ -798,6 +821,12 @@ static int smack_set_mnt_opts(struct super_block *sb, > if (transmute) > isp->smk_flags |= SMK_INODE_TRANSMUTE; > > + /* > + * Set the superblock namespace from a mounting process > + */ > + put_user_ns(sp->smk_ns); > + sp->smk_ns = get_user_ns(ns); > + > return 0; > } > > @@ -848,7 +877,7 @@ static int smack_sb_statfs(struct dentry *dentry) > smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); > smk_ad_setfield_u_fs_path_dentry(&ad, dentry); > > - rc = smk_curacc(sbp->smk_floor, MAY_READ, &ad); > + rc = smk_curacc(sbp->smk_floor, sbp->smk_ns, MAY_READ, &ad); > rc = smk_bu_current("statfs", sbp->smk_floor, MAY_READ, rc); > return rc; > } > @@ -868,6 +897,7 @@ static int smack_bprm_set_creds(struct linux_binprm *bprm) > struct inode *inode = file_inode(bprm->file); > struct task_smack *bsp = bprm->cred->security; > struct inode_smack *isp; > + struct user_namespace *ns = ns_of_current(); > int rc; > > if (bprm->cred_prepared) > @@ -877,6 +907,13 @@ static int smack_bprm_set_creds(struct linux_binprm *bprm) > if (isp->smk_task == NULL || isp->smk_task == bsp->smk_task) > return 0; > > +#ifdef CONFIG_SECURITY_SMACK_NS > + /* one label version of smk_labels_valid() */ > + if (smk_find_mapped_ns(ns) && > + smk_find_mapped(isp->smk_task, ns) == NULL) > + return -EACCES; > +#endif > + > if (bprm->unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) { > struct task_struct *tracer; > rc = 0; > @@ -884,9 +921,8 @@ static int smack_bprm_set_creds(struct linux_binprm *bprm) > rcu_read_lock(); > tracer = ptrace_parent(current); > if (likely(tracer != NULL)) > - rc = smk_ptrace_rule_check(tracer, > - isp->smk_task, > - PTRACE_MODE_ATTACH, > + rc = smk_ptrace_rule_check(tracer, isp->smk_task, > + ns, PTRACE_MODE_ATTACH, > __func__); > rcu_read_unlock(); > > @@ -1027,6 +1063,7 @@ static int smack_inode_link(struct dentry *old_dentry, struct inode *dir, > struct dentry *new_dentry) > { > struct smack_known *isp; > + struct user_namespace *ns = ns_of_current(); > struct smk_audit_info ad; > int rc; > > @@ -1034,13 +1071,13 @@ static int smack_inode_link(struct dentry *old_dentry, struct inode *dir, > smk_ad_setfield_u_fs_path_dentry(&ad, old_dentry); > > isp = smk_of_inode(d_backing_inode(old_dentry)); > - rc = smk_curacc(isp, MAY_WRITE, &ad); > + rc = smk_curacc(isp, ns, MAY_WRITE, &ad); > rc = smk_bu_inode(d_backing_inode(old_dentry), MAY_WRITE, rc); > > if (rc == 0 && d_is_positive(new_dentry)) { > isp = smk_of_inode(d_backing_inode(new_dentry)); > smk_ad_setfield_u_fs_path_dentry(&ad, new_dentry); > - rc = smk_curacc(isp, MAY_WRITE, &ad); > + rc = smk_curacc(isp, ns, MAY_WRITE, &ad); > rc = smk_bu_inode(d_backing_inode(new_dentry), MAY_WRITE, rc); > } > > @@ -1058,6 +1095,7 @@ static int smack_inode_link(struct dentry *old_dentry, struct inode *dir, > static int smack_inode_unlink(struct inode *dir, struct dentry *dentry) > { > struct inode *ip = d_backing_inode(dentry); > + struct user_namespace *ns = ns_of_current(); > struct smk_audit_info ad; > int rc; > > @@ -1067,7 +1105,7 @@ static int smack_inode_unlink(struct inode *dir, struct dentry *dentry) > /* > * You need write access to the thing you're unlinking > */ > - rc = smk_curacc(smk_of_inode(ip), MAY_WRITE, &ad); > + rc = smk_curacc(smk_of_inode(ip), ns, MAY_WRITE, &ad); > rc = smk_bu_inode(ip, MAY_WRITE, rc); > if (rc == 0) { > /* > @@ -1075,7 +1113,7 @@ static int smack_inode_unlink(struct inode *dir, struct dentry *dentry) > */ > smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_INODE); > smk_ad_setfield_u_fs_inode(&ad, dir); > - rc = smk_curacc(smk_of_inode(dir), MAY_WRITE, &ad); > + rc = smk_curacc(smk_of_inode(dir), ns, MAY_WRITE, &ad); > rc = smk_bu_inode(dir, MAY_WRITE, rc); > } > return rc; > @@ -1091,6 +1129,7 @@ static int smack_inode_unlink(struct inode *dir, struct dentry *dentry) > */ > static int smack_inode_rmdir(struct inode *dir, struct dentry *dentry) > { > + struct user_namespace *ns = ns_of_current(); > struct smk_audit_info ad; > int rc; > > @@ -1100,7 +1139,8 @@ static int smack_inode_rmdir(struct inode *dir, struct dentry *dentry) > /* > * You need write access to the thing you're removing > */ > - rc = smk_curacc(smk_of_inode(d_backing_inode(dentry)), MAY_WRITE, &ad); > + rc = smk_curacc(smk_of_inode(d_backing_inode(dentry)), ns, > + MAY_WRITE, &ad); > rc = smk_bu_inode(d_backing_inode(dentry), MAY_WRITE, rc); > if (rc == 0) { > /* > @@ -1108,7 +1148,7 @@ static int smack_inode_rmdir(struct inode *dir, struct dentry *dentry) > */ > smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_INODE); > smk_ad_setfield_u_fs_inode(&ad, dir); > - rc = smk_curacc(smk_of_inode(dir), MAY_WRITE, &ad); > + rc = smk_curacc(smk_of_inode(dir), ns, MAY_WRITE, &ad); > rc = smk_bu_inode(dir, MAY_WRITE, rc); > } > > @@ -1132,21 +1172,22 @@ static int smack_inode_rename(struct inode *old_inode, > struct inode *new_inode, > struct dentry *new_dentry) > { > - int rc; > struct smack_known *isp; > + struct user_namespace *ns = ns_of_current(); > struct smk_audit_info ad; > + int rc; > > smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); > smk_ad_setfield_u_fs_path_dentry(&ad, old_dentry); > > isp = smk_of_inode(d_backing_inode(old_dentry)); > - rc = smk_curacc(isp, MAY_READWRITE, &ad); > + rc = smk_curacc(isp, ns, MAY_READWRITE, &ad); > rc = smk_bu_inode(d_backing_inode(old_dentry), MAY_READWRITE, rc); > > if (rc == 0 && d_is_positive(new_dentry)) { > isp = smk_of_inode(d_backing_inode(new_dentry)); > smk_ad_setfield_u_fs_path_dentry(&ad, new_dentry); > - rc = smk_curacc(isp, MAY_READWRITE, &ad); > + rc = smk_curacc(isp, ns, MAY_READWRITE, &ad); > rc = smk_bu_inode(d_backing_inode(new_dentry), MAY_READWRITE, rc); > } > return rc; > @@ -1163,6 +1204,7 @@ static int smack_inode_rename(struct inode *old_inode, > */ > static int smack_inode_permission(struct inode *inode, int mask) > { > + struct user_namespace *ns = ns_of_current(); > struct smk_audit_info ad; > int no_block = mask & MAY_NOT_BLOCK; > int rc; > @@ -1179,7 +1221,7 @@ static int smack_inode_permission(struct inode *inode, int mask) > return -ECHILD; > smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_INODE); > smk_ad_setfield_u_fs_inode(&ad, inode); > - rc = smk_curacc(smk_of_inode(inode), mask, &ad); > + rc = smk_curacc(smk_of_inode(inode), ns, mask, &ad); > rc = smk_bu_inode(inode, mask, rc); > return rc; > } > @@ -1193,6 +1235,7 @@ static int smack_inode_permission(struct inode *inode, int mask) > */ > static int smack_inode_setattr(struct dentry *dentry, struct iattr *iattr) > { > + struct user_namespace *ns = ns_of_current(); > struct smk_audit_info ad; > int rc; > > @@ -1204,7 +1247,8 @@ static int smack_inode_setattr(struct dentry *dentry, struct iattr *iattr) > smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); > smk_ad_setfield_u_fs_path_dentry(&ad, dentry); > > - rc = smk_curacc(smk_of_inode(d_backing_inode(dentry)), MAY_WRITE, &ad); > + rc = smk_curacc(smk_of_inode(d_backing_inode(dentry)), ns, > + MAY_WRITE, &ad); > rc = smk_bu_inode(d_backing_inode(dentry), MAY_WRITE, rc); > return rc; > } > @@ -1218,13 +1262,14 @@ static int smack_inode_setattr(struct dentry *dentry, struct iattr *iattr) > */ > static int smack_inode_getattr(const struct path *path) > { > + struct user_namespace *ns = ns_of_current(); > struct smk_audit_info ad; > struct inode *inode = d_backing_inode(path->dentry); > int rc; > > smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); > smk_ad_setfield_u_fs_path(&ad, *path); > - rc = smk_curacc(smk_of_inode(inode), MAY_READ, &ad); > + rc = smk_curacc(smk_of_inode(inode), ns, MAY_READ, &ad); > rc = smk_bu_inode(inode, MAY_READ, rc); > return rc; > } > @@ -1246,6 +1291,9 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name, > { > struct smk_audit_info ad; > struct smack_known *skp; > + struct smack_known *sbj = smk_of_current(); > + struct smack_known *obj = smk_of_inode(d_backing_inode(dentry)); > + struct user_namespace *ns = ns_of_current(); > int check_priv = 0; > int check_import = 0; > int check_star = 0; > @@ -1272,11 +1320,12 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name, > } else > rc = cap_inode_setxattr(dentry, name, value, size, flags); > > - if (check_priv && !smack_privileged(CAP_MAC_ADMIN)) > + if (check_priv && !(smk_labels_valid(sbj, obj, ns) && > + smack_ns_privileged(ns, CAP_MAC_ADMIN))) > rc = -EPERM; > > if (rc == 0 && check_import) { > - skp = size ? smk_get_label(value, size, true) : NULL; > + skp = size ? smk_get_label(value, size, true, ns) : NULL; > if (IS_ERR(skp)) > rc = PTR_ERR(skp); > else if (skp == NULL || (check_star && > @@ -1288,7 +1337,7 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name, > smk_ad_setfield_u_fs_path_dentry(&ad, dentry); > > if (rc == 0) { > - rc = smk_curacc(smk_of_inode(d_backing_inode(dentry)), MAY_WRITE, &ad); > + rc = smk_curacc(obj, ns, MAY_WRITE, &ad); > rc = smk_bu_inode(d_backing_inode(dentry), MAY_WRITE, rc); > } > > @@ -1296,6 +1345,40 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name, > } > > /** > + * smack_inode_pre_setxattr - Unmap the namespaced label > + * @dentry: object > + * @name: attribute name > + * @value: attribute value > + * @size: attribute size > + * @flags: unused > + * @alloc: unused > + * > + * Guarantees that the real label value will be written to the filesystem. > + */ > +static int smack_inode_pre_setxattr(struct dentry *dentry, const char *name, > + const void **value, size_t *size, int flags, > + bool *alloc) > +{ > + struct smack_known *skp; > + struct user_namespace *ns = ns_of_current(); > + > + if (strcmp(name, XATTR_NAME_SMACK) != 0 && > + strcmp(name, XATTR_NAME_SMACKEXEC) != 0 && > + strcmp(name, XATTR_NAME_SMACKMMAP) != 0) > + return 0; > + > + /* Convert value to non namespaced label */ > + skp = smk_get_label(*value, *size, true, ns); > + if (IS_ERR(skp)) > + return PTR_ERR(skp); > + > + *value = skp->smk_known; > + *size = strlen(skp->smk_known); > + > + return 0; > +} > + > +/** > * smack_inode_post_setxattr - Apply the Smack update approved above > * @dentry: object > * @name: attribute name > @@ -1326,7 +1409,8 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name, > skpp = &isp->smk_mmap; > > if (skpp) { > - skp = smk_get_label(value, size, true); > + /* value has been un-namespaced in inode_pre_setxattr() */ > + skp = smk_get_label(value, size, true, &init_user_ns); > > if (!IS_ERR(skp)) > *skpp = skp; > @@ -1344,13 +1428,15 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name, > */ > static int smack_inode_getxattr(struct dentry *dentry, const char *name) > { > + struct user_namespace *ns = ns_of_current(); > struct smk_audit_info ad; > int rc; > > smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); > smk_ad_setfield_u_fs_path_dentry(&ad, dentry); > > - rc = smk_curacc(smk_of_inode(d_backing_inode(dentry)), MAY_READ, &ad); > + rc = smk_curacc(smk_of_inode(d_backing_inode(dentry)), ns, > + MAY_READ, &ad); > rc = smk_bu_inode(d_backing_inode(dentry), MAY_READ, rc); > return rc; > } > @@ -1367,6 +1453,9 @@ static int smack_inode_getxattr(struct dentry *dentry, const char *name) > static int smack_inode_removexattr(struct dentry *dentry, const char *name) > { > struct inode_smack *isp; > + struct smack_known *sbj = smk_of_current(); > + struct smack_known *obj = smk_of_inode(d_backing_inode(dentry)); > + struct user_namespace *ns = ns_of_current(); > struct smk_audit_info ad; > int rc = 0; > > @@ -1376,7 +1465,8 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name) > strcmp(name, XATTR_NAME_SMACKEXEC) == 0 || > strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0 || > strcmp(name, XATTR_NAME_SMACKMMAP) == 0) { > - if (!smack_privileged(CAP_MAC_ADMIN)) > + if (!smk_labels_valid(sbj, obj, ns) || > + !smack_ns_privileged(ns, CAP_MAC_ADMIN)) > rc = -EPERM; > } else > rc = cap_inode_removexattr(dentry, name); > @@ -1387,7 +1477,7 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name) > smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); > smk_ad_setfield_u_fs_path_dentry(&ad, dentry); > > - rc = smk_curacc(smk_of_inode(d_backing_inode(dentry)), MAY_WRITE, &ad); > + rc = smk_curacc(obj, ns, MAY_WRITE, &ad); > rc = smk_bu_inode(d_backing_inode(dentry), MAY_WRITE, rc); > if (rc != 0) > return rc; > @@ -1427,13 +1517,18 @@ static int smack_inode_getsecurity(const struct inode *inode, > struct super_block *sbp; > struct inode *ip = (struct inode *)inode; > struct smack_known *isp = NULL; > + struct user_namespace *ns = ns_of_current(); > int rc = 0; > > if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) > isp = smk_of_inode(inode); > + else if (strcmp(name, XATTR_SMACK_EXEC) == 0) > + isp = smk_of_exec(inode); > + else if (strcmp(name, XATTR_SMACK_MMAP) == 0) > + isp = smk_of_mmap(inode); > > if (isp) { > - *buffer = smk_find_label_name(isp); > + *buffer = smk_find_label_name(isp, ns); > if (*buffer == NULL) > *buffer = smack_known_huh.smk_known; > return strlen(*buffer); > @@ -1460,7 +1555,7 @@ static int smack_inode_getsecurity(const struct inode *inode, > return -EOPNOTSUPP; > > if (rc == 0) { > - *buffer = smk_find_label_name(isp); > + *buffer = smk_find_label_name(isp, ns); > if (*buffer == NULL) > *buffer = smack_known_huh.smk_known; > rc = strlen(*buffer); > @@ -1571,18 +1666,19 @@ static int smack_file_ioctl(struct file *file, unsigned int cmd, > { > int rc = 0; > struct smk_audit_info ad; > + struct user_namespace *ns = ns_of_current(); > struct inode *inode = file_inode(file); > > smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); > smk_ad_setfield_u_fs_path(&ad, file->f_path); > > if (_IOC_DIR(cmd) & _IOC_WRITE) { > - rc = smk_curacc(smk_of_inode(inode), MAY_WRITE, &ad); > + rc = smk_curacc(smk_of_inode(inode), ns, MAY_WRITE, &ad); > rc = smk_bu_file(file, MAY_WRITE, rc); > } > > if (rc == 0 && (_IOC_DIR(cmd) & _IOC_READ)) { > - rc = smk_curacc(smk_of_inode(inode), MAY_READ, &ad); > + rc = smk_curacc(smk_of_inode(inode), ns, MAY_READ, &ad); > rc = smk_bu_file(file, MAY_READ, rc); > } > > @@ -1600,11 +1696,12 @@ static int smack_file_lock(struct file *file, unsigned int cmd) > { > struct smk_audit_info ad; > int rc; > + struct user_namespace *ns = ns_of_current(); > struct inode *inode = file_inode(file); > > smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); > smk_ad_setfield_u_fs_path(&ad, file->f_path); > - rc = smk_curacc(smk_of_inode(inode), MAY_LOCK, &ad); > + rc = smk_curacc(smk_of_inode(inode), ns, MAY_LOCK, &ad); > rc = smk_bu_file(file, MAY_LOCK, rc); > return rc; > } > @@ -1626,6 +1723,7 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd, > { > struct smk_audit_info ad; > int rc = 0; > + struct user_namespace *ns = ns_of_current(); > struct inode *inode = file_inode(file); > > switch (cmd) { > @@ -1635,14 +1733,14 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd, > case F_SETLKW: > smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); > smk_ad_setfield_u_fs_path(&ad, file->f_path); > - rc = smk_curacc(smk_of_inode(inode), MAY_LOCK, &ad); > + rc = smk_curacc(smk_of_inode(inode), ns, MAY_LOCK, &ad); > rc = smk_bu_file(file, MAY_LOCK, rc); > break; > case F_SETOWN: > case F_SETSIG: > smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); > smk_ad_setfield_u_fs_path(&ad, file->f_path); > - rc = smk_curacc(smk_of_inode(inode), MAY_WRITE, &ad); > + rc = smk_curacc(smk_of_inode(inode), ns, MAY_WRITE, &ad); > rc = smk_bu_file(file, MAY_WRITE, rc); > break; > default: > @@ -1672,6 +1770,7 @@ static int smack_mmap_file(struct file *file, > struct task_smack *tsp; > struct smack_known *okp; > struct inode_smack *isp; > + struct user_namespace *sns; > int may; > int mmay; > int tmay; > @@ -1682,12 +1781,16 @@ static int smack_mmap_file(struct file *file, > > tsp = current_security(); > skp = smk_of_task(tsp); > + sns = ns_of_current(); > isp = file_inode(file)->i_security; > mkp = isp->smk_mmap; > > if (mkp == NULL) > return 0; > > + if (!smk_labels_valid(skp, mkp, sns)) > + return -EACCES; > + > rc = 0; > > rcu_read_lock(); > @@ -1703,6 +1806,7 @@ static int smack_mmap_file(struct file *file, > */ > if (mkp->smk_known == okp->smk_known) > continue; > + > /* > * If there is a matching local rule take > * that into account as well. > @@ -1782,8 +1886,10 @@ static int smack_file_send_sigiotask(struct task_struct *tsk, > struct fown_struct *fown, int signum) > { > struct smack_known *skp; > - struct smack_known *tkp = smk_of_task(tsk->cred->security); > + struct smack_known *tkp; > struct file *file; > + struct user_namespace *sns; > + struct user_namespace *tns; > int rc; > struct smk_audit_info ad; > > @@ -1791,12 +1897,17 @@ static int smack_file_send_sigiotask(struct task_struct *tsk, > * struct fown_struct is never outside the context of a struct file > */ > file = container_of(fown, struct file, f_owner); > + skp = file->f_security; > + sns = file->f_cred->user_ns; > + > + tkp = smk_of_task_struct(tsk); > + tns = ns_of_task_struct(tsk); > > /* we don't log here as rc can be overriden */ > - skp = file->f_security; > - rc = smk_access(skp, tkp, MAY_WRITE, NULL); > + rc = smk_access(skp, tkp, sns, MAY_WRITE, NULL); > rc = smk_bu_note("sigiotask", skp, tkp, MAY_WRITE, rc); > - if (rc != 0 && smack_has_privilege(tsk, CAP_MAC_OVERRIDE)) > + if (rc != 0 && smk_labels_valid(skp, tkp, sns) > + && smack_has_ns_privilege(tsk, tns, CAP_MAC_OVERRIDE)) > rc = 0; > > smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); > @@ -1816,6 +1927,7 @@ static int smack_file_receive(struct file *file) > int rc; > int may = 0; > struct smk_audit_info ad; > + struct user_namespace *ns = ns_of_current(); > struct inode *inode = file_inode(file); > > if (unlikely(IS_PRIVATE(inode))) > @@ -1831,7 +1943,7 @@ static int smack_file_receive(struct file *file) > if (file->f_mode & FMODE_WRITE) > may |= MAY_WRITE; > > - rc = smk_curacc(smk_of_inode(inode), may, &ad); > + rc = smk_curacc(smk_of_inode(inode), ns, may, &ad); > rc = smk_bu_file(file, may, rc); > return rc; > } > @@ -1851,16 +1963,19 @@ static int smack_file_receive(struct file *file) > static int smack_file_open(struct file *file, const struct cred *cred) > { > struct task_smack *tsp = cred->security; > + struct user_namespace *ns = cred->user_ns; > struct inode *inode = file_inode(file); > + struct inode_smack *isp = file_inode(file)->i_security; > struct smk_audit_info ad; > int rc; > > - if (smack_privileged(CAP_MAC_OVERRIDE)) > + if (smk_labels_valid(tsp->smk_task, isp->smk_inode, ns) && > + smack_ns_privileged(ns, CAP_MAC_OVERRIDE)) > return 0; > > smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); > smk_ad_setfield_u_fs_path(&ad, file->f_path); > - rc = smk_access(tsp->smk_task, smk_of_inode(inode), MAY_READ, &ad); > + rc = smk_access(tsp->smk_task, smk_of_inode(inode), ns, MAY_READ, &ad); > rc = smk_bu_credfile(cred, file, MAY_READ, rc); > > return rc; > @@ -2015,12 +2130,13 @@ static int smk_curacc_on_task(struct task_struct *p, int access, > const char *caller) > { > struct smk_audit_info ad; > - struct smack_known *skp = smk_of_task_struct(p); > + struct smack_known *tkp = smk_of_task_struct(p); > + struct user_namespace *tns = ns_of_task_struct(p); > int rc; > > smk_ad_init(&ad, caller, LSM_AUDIT_DATA_TASK); > smk_ad_setfield_u_tsk(&ad, p); > - rc = smk_curacc(skp, access, &ad); > + rc = smk_curacc(tkp, tns, access, &ad); > rc = smk_bu_task(p, access, rc); > return rc; > } > @@ -2161,6 +2277,7 @@ static int smack_task_kill(struct task_struct *p, struct siginfo *info, > struct smk_audit_info ad; > struct smack_known *skp; > struct smack_known *tkp = smk_of_task_struct(p); > + struct user_namespace *tns = ns_of_task_struct(p); > int rc; > > smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); > @@ -2170,7 +2287,7 @@ static int smack_task_kill(struct task_struct *p, struct siginfo *info, > * can write the receiver. > */ > if (secid == 0) { > - rc = smk_curacc(tkp, MAY_WRITE, &ad); > + rc = smk_curacc(tkp, tns, MAY_WRITE, &ad); > rc = smk_bu_task(p, MAY_WRITE, rc); > return rc; > } > @@ -2180,8 +2297,9 @@ static int smack_task_kill(struct task_struct *p, struct siginfo *info, > * we can't take privilege into account. > */ > skp = smack_from_secid(secid); > - rc = smk_access(skp, tkp, MAY_WRITE, &ad); > + rc = smk_access(skp, tkp, tns, MAY_WRITE, &ad); > rc = smk_bu_note("USB signal", skp, tkp, MAY_WRITE, rc); > + > return rc; > } > > @@ -2236,6 +2354,7 @@ static void smack_task_to_inode(struct task_struct *p, struct inode *inode) > static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags) > { > struct smack_known *skp = smk_of_current(); > + struct user_namespace *ns = ns_of_current(); > struct socket_smack *ssp; > > ssp = kzalloc(sizeof(struct socket_smack), gfp_flags); > @@ -2245,6 +2364,7 @@ static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags) > ssp->smk_in = skp; > ssp->smk_out = skp; > ssp->smk_packet = NULL; > + ssp->smk_ns = get_user_ns(ns); > > sk->sk_security = ssp; > > @@ -2259,7 +2379,11 @@ static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags) > */ > static void smack_sk_free_security(struct sock *sk) > { > + struct socket_smack *ssp = sk->sk_security; > + > + put_user_ns(ssp->smk_ns); > kfree(sk->sk_security); > + sk->sk_security = NULL; > } > > /** > @@ -2420,6 +2544,7 @@ static int smack_netlabel(struct sock *sk, int labeled) > static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap) > { > struct smack_known *skp; > + struct user_namespace *sns; > int rc; > int sk_lbl; > struct smack_known *hkp; > @@ -2439,7 +2564,8 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap) > #endif > sk_lbl = SMACK_UNLABELED_SOCKET; > skp = ssp->smk_out; > - rc = smk_access(skp, hkp, MAY_WRITE, &ad); > + sns = ssp->smk_ns; > + rc = smk_access(skp, hkp, sns, MAY_WRITE, &ad); > rc = smk_bu_note("IPv4 host check", skp, hkp, MAY_WRITE, rc); > } else { > sk_lbl = SMACK_CIPSO_SOCKET; > @@ -2464,6 +2590,7 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap) > */ > static int smk_ipv6_check(struct smack_known *subject, > struct smack_known *object, > + struct user_namespace *ns, > struct sockaddr_in6 *address, int act) > { > #ifdef CONFIG_AUDIT > @@ -2481,7 +2608,7 @@ static int smk_ipv6_check(struct smack_known *subject, > else > ad.a.u.net->v6info.daddr = address->sin6_addr; > #endif > - rc = smk_access(subject, object, MAY_WRITE, &ad); > + rc = smk_access(subject, object, ns, MAY_WRITE, &ad); > rc = smk_bu_note("IPv6 check", subject, object, MAY_WRITE, rc); > return rc; > } > @@ -2574,6 +2701,7 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address, > struct smk_port_label *spp; > struct socket_smack *ssp = sk->sk_security; > struct smack_known *skp = NULL; > + struct user_namespace *sns = ssp->smk_ns; > unsigned short port; > struct smack_known *object; > > @@ -2617,7 +2745,7 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address, > break; > } > > - return smk_ipv6_check(skp, object, address, act); > + return smk_ipv6_check(skp, object, sns, address, act); > } > #endif /* SMACK_IPV6_PORT_LABELING */ > > @@ -2640,12 +2768,13 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name, > struct inode_smack *nsp = inode->i_security; > struct socket_smack *ssp; > struct socket *sock; > + struct user_namespace *ns = ns_of_current(); > int rc = 0; > > if (value == NULL || size > SMK_LONGLABEL || size == 0) > return -EINVAL; > > - skp = smk_get_label(value, size, true); > + skp = smk_get_label(value, size, true, ns); > if (IS_ERR(skp)) > return PTR_ERR(skp); > > @@ -2765,6 +2894,7 @@ static int smack_socket_connect(struct socket *sock, struct sockaddr *sap, > #ifdef SMACK_IPV6_SECMARK_LABELING > struct smack_known *rsp; > struct socket_smack *ssp = sock->sk->sk_security; > + struct user_namespace *sns = ssp->smk_ns; > #endif > > if (sock->sk == NULL) > @@ -2782,7 +2912,7 @@ static int smack_socket_connect(struct socket *sock, struct sockaddr *sap, > #ifdef SMACK_IPV6_SECMARK_LABELING > rsp = smack_ipv6host_label(sip); > if (rsp != NULL) > - rc = smk_ipv6_check(ssp->smk_out, rsp, sip, > + rc = smk_ipv6_check(ssp->smk_out, rsp, sns, sip, > SMK_CONNECTING); > #endif > #ifdef SMACK_IPV6_PORT_LABELING > @@ -2839,14 +2969,14 @@ static void smack_msg_msg_free_security(struct msg_msg *msg) > } > > /** > - * smack_of_shm - the smack pointer for the shm > + * security_of_shm - the smack pointer for the shm > * @shp: the object > * > - * Returns a pointer to the smack value > + * Returns a pointer to the security_smack struct > */ > -static struct smack_known *smack_of_shm(struct shmid_kernel *shp) > +static struct ipc_smack *security_of_shm(struct shmid_kernel *shp) > { > - return (struct smack_known *)shp->shm_perm.security; > + return (struct ipc_smack *)shp->shm_perm.security; > } > > /** > @@ -2858,9 +2988,16 @@ static struct smack_known *smack_of_shm(struct shmid_kernel *shp) > static int smack_shm_alloc_security(struct shmid_kernel *shp) > { > struct kern_ipc_perm *isp = &shp->shm_perm; > - struct smack_known *skp = smk_of_current(); > + struct ipc_smack *ssp; > + > + ssp = kzalloc(sizeof(struct ipc_smack), GFP_KERNEL); > + if (ssp == NULL) > + return -ENOMEM; > + > + ssp->smk_known = smk_of_current(); > + ssp->smk_ns = get_user_ns(ns_of_current()); > > - isp->security = skp; > + isp->security = ssp; > return 0; > } > > @@ -2873,7 +3010,10 @@ static int smack_shm_alloc_security(struct shmid_kernel *shp) > static void smack_shm_free_security(struct shmid_kernel *shp) > { > struct kern_ipc_perm *isp = &shp->shm_perm; > + struct ipc_smack *ssp = isp->security; > > + put_user_ns(ssp->smk_ns); > + kfree(isp->security); > isp->security = NULL; > } > > @@ -2886,7 +3026,7 @@ static void smack_shm_free_security(struct shmid_kernel *shp) > */ > static int smk_curacc_shm(struct shmid_kernel *shp, int access) > { > - struct smack_known *ssp = smack_of_shm(shp); > + struct ipc_smack *ssp = security_of_shm(shp); > struct smk_audit_info ad; > int rc; > > @@ -2894,8 +3034,8 @@ static int smk_curacc_shm(struct shmid_kernel *shp, int access) > smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC); > ad.a.u.ipc_id = shp->shm_perm.id; > #endif > - rc = smk_curacc(ssp, access, &ad); > - rc = smk_bu_current("shm", ssp, access, rc); > + rc = smk_curacc(ssp->smk_known, ssp->smk_ns, access, &ad); > + rc = smk_bu_current("shm", ssp->smk_known, access, rc); > return rc; > } > > @@ -2966,14 +3106,14 @@ static int smack_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr, > } > > /** > - * smack_of_sem - the smack pointer for the sem > + * security_of_sem - the smack pointer for the sem > * @sma: the object > * > - * Returns a pointer to the smack value > + * Returns a pointer to the ipc_smack struct > */ > -static struct smack_known *smack_of_sem(struct sem_array *sma) > +static struct ipc_smack *security_of_sem(struct sem_array *sma) > { > - return (struct smack_known *)sma->sem_perm.security; > + return (struct ipc_smack *)sma->sem_perm.security; > } > > /** > @@ -2985,9 +3125,16 @@ static struct smack_known *smack_of_sem(struct sem_array *sma) > static int smack_sem_alloc_security(struct sem_array *sma) > { > struct kern_ipc_perm *isp = &sma->sem_perm; > - struct smack_known *skp = smk_of_current(); > + struct ipc_smack *ssp; > + > + ssp = kzalloc(sizeof(struct ipc_smack), GFP_KERNEL); > + if (ssp == NULL) > + return -ENOMEM; > + > + ssp->smk_known = smk_of_current(); > + ssp->smk_ns = get_user_ns(ns_of_current()); > > - isp->security = skp; > + isp->security = ssp; > return 0; > } > > @@ -3000,7 +3147,10 @@ static int smack_sem_alloc_security(struct sem_array *sma) > static void smack_sem_free_security(struct sem_array *sma) > { > struct kern_ipc_perm *isp = &sma->sem_perm; > + struct ipc_smack *ssp = isp->security; > > + put_user_ns(ssp->smk_ns); > + kfree(isp->security); > isp->security = NULL; > } > > @@ -3013,7 +3163,7 @@ static void smack_sem_free_security(struct sem_array *sma) > */ > static int smk_curacc_sem(struct sem_array *sma, int access) > { > - struct smack_known *ssp = smack_of_sem(sma); > + struct ipc_smack *ssp = security_of_sem(sma); > struct smk_audit_info ad; > int rc; > > @@ -3021,8 +3171,8 @@ static int smk_curacc_sem(struct sem_array *sma, int access) > smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC); > ad.a.u.ipc_id = sma->sem_perm.id; > #endif > - rc = smk_curacc(ssp, access, &ad); > - rc = smk_bu_current("sem", ssp, access, rc); > + rc = smk_curacc(ssp->smk_known, ssp->smk_ns, access, &ad); > + rc = smk_bu_current("sem", ssp->smk_known, access, rc); > return rc; > } > > @@ -3107,9 +3257,16 @@ static int smack_sem_semop(struct sem_array *sma, struct sembuf *sops, > static int smack_msg_queue_alloc_security(struct msg_queue *msq) > { > struct kern_ipc_perm *kisp = &msq->q_perm; > - struct smack_known *skp = smk_of_current(); > + struct ipc_smack *ssp; > + > + ssp = kzalloc(sizeof(struct ipc_smack), GFP_KERNEL); > + if (ssp == NULL) > + return -ENOMEM; > > - kisp->security = skp; > + ssp->smk_known = smk_of_current(); > + ssp->smk_ns = get_user_ns(ns_of_current()); > + > + kisp->security = ssp; > return 0; > } > > @@ -3122,19 +3279,22 @@ static int smack_msg_queue_alloc_security(struct msg_queue *msq) > static void smack_msg_queue_free_security(struct msg_queue *msq) > { > struct kern_ipc_perm *kisp = &msq->q_perm; > + struct ipc_smack *ssp = kisp->security; > > + put_user_ns(ssp->smk_ns); > + kfree(kisp->security); > kisp->security = NULL; > } > > /** > - * smack_of_msq - the smack pointer for the msq > + * security_of_msq - the smack pointer for the msq > * @msq: the object > * > - * Returns a pointer to the smack label entry > + * Returns a pointer to the ipc_smack struct > */ > -static struct smack_known *smack_of_msq(struct msg_queue *msq) > +static struct ipc_smack *security_of_msq(struct msg_queue *msq) > { > - return (struct smack_known *)msq->q_perm.security; > + return (struct ipc_smack *)msq->q_perm.security; > } > > /** > @@ -3146,7 +3306,7 @@ static struct smack_known *smack_of_msq(struct msg_queue *msq) > */ > static int smk_curacc_msq(struct msg_queue *msq, int access) > { > - struct smack_known *msp = smack_of_msq(msq); > + struct ipc_smack *msp = security_of_msq(msq); > struct smk_audit_info ad; > int rc; > > @@ -3154,8 +3314,8 @@ static int smk_curacc_msq(struct msg_queue *msq, int access) > smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC); > ad.a.u.ipc_id = msq->q_perm.id; > #endif > - rc = smk_curacc(msp, access, &ad); > - rc = smk_bu_current("msq", msp, access, rc); > + rc = smk_curacc(msp->smk_known, msp->smk_ns, access, &ad); > + rc = smk_bu_current("msq", msp->smk_known, access, rc); > return rc; > } > > @@ -3249,7 +3409,7 @@ static int smack_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, > */ > static int smack_ipc_permission(struct kern_ipc_perm *ipp, short flag) > { > - struct smack_known *iskp = ipp->security; > + struct ipc_smack *isp = ipp->security; > int may = smack_flags_to_may(flag); > struct smk_audit_info ad; > int rc; > @@ -3258,8 +3418,8 @@ static int smack_ipc_permission(struct kern_ipc_perm *ipp, short flag) > smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC); > ad.a.u.ipc_id = ipp->id; > #endif > - rc = smk_curacc(iskp, may, &ad); > - rc = smk_bu_current("svipc", iskp, may, rc); > + rc = smk_curacc(isp->smk_known, isp->smk_ns, may, &ad); > + rc = smk_bu_current("svipc", isp->smk_known, may, rc); > return rc; > } > > @@ -3270,9 +3430,9 @@ static int smack_ipc_permission(struct kern_ipc_perm *ipp, short flag) > */ > static void smack_ipc_getsecid(struct kern_ipc_perm *ipp, u32 *secid) > { > - struct smack_known *iskp = ipp->security; > + struct ipc_smack *iskp = ipp->security; > > - *secid = iskp->smk_secid; > + *secid = iskp->smk_known->smk_secid; > } > > /** > @@ -3530,13 +3690,14 @@ int smack_getprocattr_seq(struct task_struct *p, const char *name, > static int smack_getprocattr(struct task_struct *p, char *name, char **value) > { > struct smack_known *skp = smk_of_task_struct(p); > + struct user_namespace *ns = ns_of_current(); > char *cp; > int slen; > > if (strcmp(name, "current") != 0) > return -EINVAL; > > - cp = smk_find_label_name(skp); > + cp = smk_find_label_name(skp, ns); > if (cp == NULL) > cp = smack_known_huh.smk_known; > cp = kstrdup(cp, GFP_KERNEL); > @@ -3564,6 +3725,7 @@ static int proc_current_write(struct task_struct *p, void *value, size_t size) > struct task_smack *tsp; > struct cred *new; > struct smack_known *skp; > + struct user_namespace *ns; > > /* > * Changing another process' Smack value is too dangerous > @@ -3572,13 +3734,15 @@ static int proc_current_write(struct task_struct *p, void *value, size_t size) > if (p != current) > return -EPERM; > > - if (!smack_privileged(CAP_MAC_ADMIN)) > + ns = ns_of_current(); > + > + if (!smack_ns_privileged(ns, CAP_MAC_ADMIN)) > return -EPERM; > > if (value == NULL || size == 0 || size >= SMK_LONGLABEL) > return -EINVAL; > > - skp = smk_get_label(value, size, true); > + skp = smk_get_label(value, size, true, ns); > if (IS_ERR(skp)) > return PTR_ERR(skp); > > @@ -3645,23 +3809,27 @@ static int smack_unix_stream_connect(struct sock *sock, > struct smack_known *okp_out = osp->smk_out; > struct smack_known *skp_in = ssp->smk_in; > struct smack_known *okp_in = osp->smk_in; > + struct user_namespace *sns = ssp->smk_ns; > + struct user_namespace *ons = osp->smk_ns; > struct smk_audit_info ad; > int rc = 0; > #ifdef CONFIG_AUDIT > struct lsm_network_audit net; > #endif > > - if (!smack_privileged(CAP_MAC_OVERRIDE)) { > + if (!smack_ns_privileged(ons, CAP_MAC_OVERRIDE) || > + !smk_labels_valid(skp_out, okp_in, sns) || > + !smk_labels_valid(okp_out, skp_in, ons)) { > #ifdef CONFIG_AUDIT > smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); > smk_ad_setfield_u_net_sk(&ad, other); > #endif > - rc = smk_access(skp_out, okp_in, MAY_WRITE, &ad); > + rc = smk_access(skp_out, okp_in, sns, MAY_WRITE, &ad); > rc = smk_bu_note("UDS connect", skp_out, okp_in, MAY_WRITE, rc); > if (rc == 0) { > - rc = smk_access(okp_out, skp_in, MAY_WRITE, &ad); > + rc = smk_access(okp_out, skp_in, ons, MAY_WRITE, &ad); > rc = smk_bu_note("UDS connect", okp_out, skp_in, > - MAY_WRITE, rc); > + MAY_WRITE, rc); > } > } > > @@ -3688,6 +3856,8 @@ static int smack_unix_may_send(struct socket *sock, struct socket *other) > { > struct socket_smack *ssp = sock->sk->sk_security; > struct socket_smack *osp = other->sk->sk_security; > + struct user_namespace *sns = ssp->smk_ns; > + struct user_namespace *ons = osp->smk_ns; > struct smk_audit_info ad; > int rc; > > @@ -3698,10 +3868,11 @@ static int smack_unix_may_send(struct socket *sock, struct socket *other) > smk_ad_setfield_u_net_sk(&ad, other->sk); > #endif > > - if (smack_privileged(CAP_MAC_OVERRIDE)) > + if (smk_labels_valid(ssp->smk_out, osp->smk_in, sns) && > + smack_ns_privileged(ons, CAP_MAC_OVERRIDE)) > return 0; > > - rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad); > + rc = smk_access(ssp->smk_out, osp->smk_in, sns, MAY_WRITE, &ad); > rc = smk_bu_note("UDS send", ssp->smk_out, osp->smk_in, MAY_WRITE, rc); > return rc; > } > @@ -3724,8 +3895,9 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg, > struct sockaddr_in6 *sap = (struct sockaddr_in6 *) msg->msg_name; > #endif > #ifdef SMACK_IPV6_SECMARK_LABELING > - struct socket_smack *ssp = sock->sk->sk_security; > struct smack_known *rsp; > + struct socket_smack *ssp = sock->sk->sk_security; > + struct user_namespace *sns = ssp->smk_ns; > #endif > int rc = 0; > > @@ -3743,7 +3915,7 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg, > #ifdef SMACK_IPV6_SECMARK_LABELING > rsp = smack_ipv6host_label(sap); > if (rsp != NULL) > - rc = smk_ipv6_check(ssp->smk_out, rsp, sap, > + rc = smk_ipv6_check(ssp->smk_out, rsp, sns, sap, > SMK_CONNECTING); > #endif > #ifdef SMACK_IPV6_PORT_LABELING > @@ -3951,7 +4123,7 @@ access_check: > * This is the simplist possible security model > * for networking. > */ > - rc = smk_access(skp, ssp->smk_in, MAY_WRITE, &ad); > + rc = smk_access(skp, ssp->smk_in, ssp->smk_ns, MAY_WRITE, &ad); > rc = smk_bu_note("IPv4 delivery", skp, ssp->smk_in, > MAY_WRITE, rc); > if (rc != 0) > @@ -3975,7 +4147,7 @@ access_check: > ad.a.u.net->netif = skb->skb_iif; > ipv6_skb_to_auditdata(skb, &ad.a, NULL); > #endif /* CONFIG_AUDIT */ > - rc = smk_access(skp, ssp->smk_in, MAY_WRITE, &ad); > + rc = smk_access(skp, ssp->smk_in, ssp->smk_ns, MAY_WRITE, &ad); > rc = smk_bu_note("IPv6 delivery", skp, ssp->smk_in, > MAY_WRITE, rc); > #endif /* SMACK_IPV6_SECMARK_LABELING */ > @@ -4187,7 +4359,7 @@ access_check: > * Receiving a packet requires that the other end be able to write > * here. Read access is not required. > */ > - rc = smk_access(skp, ssp->smk_in, MAY_WRITE, &ad); > + rc = smk_access(skp, ssp->smk_in, ssp->smk_ns, MAY_WRITE, &ad); > rc = smk_bu_note("IPv4 connect", skp, ssp->smk_in, MAY_WRITE, rc); > if (rc != 0) > return rc; > @@ -4291,6 +4463,7 @@ static int smack_key_permission(key_ref_t key_ref, > struct key *keyp; > struct smk_audit_info ad; > struct smack_known *tkp = smk_of_task(cred->security); > + struct user_namespace *tns = cred->user_ns; > int request = 0; > int rc; > > @@ -4317,7 +4490,7 @@ static int smack_key_permission(key_ref_t key_ref, > request = MAY_READ; > if (perm & (KEY_NEED_WRITE | KEY_NEED_LINK | KEY_NEED_SETATTR)) > request = MAY_WRITE; > - rc = smk_access(tkp, keyp->security, request, &ad); > + rc = smk_access(tkp, keyp->security, tns, request, &ad); > rc = smk_bu_note("key access", tkp, keyp->security, request, rc); > return rc; > } > @@ -4334,6 +4507,7 @@ static int smack_key_permission(key_ref_t key_ref, > static int smack_key_getsecurity(struct key *key, char **_buffer) > { > struct smack_known *skp = key->security; > + struct user_namespace *ns = ns_of_current(); > size_t length; > char *copy; > > @@ -4342,7 +4516,7 @@ static int smack_key_getsecurity(struct key *key, char **_buffer) > return 0; > } > > - copy = smk_find_label_name(skp); > + copy = smk_find_label_name(skp, ns); > if (copy == NULL) > copy = smack_known_huh.smk_known; > copy = kstrdup(copy, GFP_KERNEL); > @@ -4520,6 +4694,11 @@ static inline void smack_userns_free(struct user_namespace *ns) > static inline int smack_userns_setns(struct nsproxy *nsproxy, > struct user_namespace *ns) > { > + struct smack_known *skp = smk_of_current(); > + > + if (smk_find_mapped(skp, ns) == NULL) > + return -EACCES; > + > return 0; > } > > @@ -4632,6 +4811,7 @@ static struct security_hook_list smack_hooks[] = { > LSM_HOOK_INIT(inode_setattr, smack_inode_setattr), > LSM_HOOK_INIT(inode_getattr, smack_inode_getattr), > LSM_HOOK_INIT(inode_setxattr, smack_inode_setxattr), > + LSM_HOOK_INIT(inode_pre_setxattr, smack_inode_pre_setxattr), > LSM_HOOK_INIT(inode_post_setxattr, smack_inode_post_setxattr), > LSM_HOOK_INIT(inode_getxattr, smack_inode_getxattr), > LSM_HOOK_INIT(inode_removexattr, smack_inode_removexattr), > diff --git a/security/smack/smack_ns.c b/security/smack/smack_ns.c > index 49223c4..dc2a666 100644 > --- a/security/smack/smack_ns.c > +++ b/security/smack/smack_ns.c > @@ -206,6 +206,45 @@ unlockout: > return sknp; > } > > +/** > + * smk_labels_valid - A helper to check whether labels are valid/mapped > + * in the namespace and can be used there > + * @sbj: a subject label to be checked > + * @obj: an object label to be checked > + * @ns: user namespace to check against (usually subject's) > + * > + * Returns true if both valid/mapped, false otherwise. > + * This helper is mostly used while checking capabilities. > + * The access functions check the validity of labels by themselves. > + */ > +bool smk_labels_valid(struct smack_known *sbj, struct smack_known *obj, > + struct user_namespace *ns) > +{ > + struct user_namespace *user_ns; > + > + /* > + * labels are always valid if there is no map > + * (init_user_ns or unmapped descendants) > + */ > + user_ns = smk_find_mapped_ns(ns); > + if (user_ns == NULL) > + return true; > + > + /* > + * If we have a map though, both labels need to be mapped. > + */ > + if (__smk_find_mapped(sbj, user_ns) == NULL) > + return false; > + if (__smk_find_mapped(obj, user_ns) == NULL) > + return false; > + > + return true; > +} > + > +/* > + * proc mapping operations > + */ > + > static void *proc_label_map_seq_start(struct seq_file *seq, loff_t *pos) > { > struct smack_known *skp; > diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c > index 3149ec0..fe4ad24 100644 > --- a/security/smack/smackfs.c > +++ b/security/smack/smackfs.c > @@ -340,13 +340,15 @@ static int smk_fill_rule(const char *subject, const char *object, > struct smack_parsed_rule *rule, int import, > int len) > { > - rule->smk_subject = smk_get_label(subject, len, import); > + struct user_namespace *ns = ns_of_current(); > + > + rule->smk_subject = smk_get_label(subject, len, import, ns); > if (IS_ERR(rule->smk_subject)) > return PTR_ERR(rule->smk_subject); > if (rule->smk_subject == NULL) > return -ENOENT; > > - rule->smk_object = smk_get_label(object, len, import); > + rule->smk_object = smk_get_label(object, len, import, ns); > if (IS_ERR(rule->smk_object)) > return PTR_ERR(rule->smk_object); > if (rule->smk_object == NULL) > @@ -573,6 +575,7 @@ static void smk_seq_stop(struct seq_file *s, void *v) > > static void smk_rule_show(struct seq_file *s, struct smack_rule *srp, int max) > { > + struct user_namespace *ns = ns_of_current(); > char *sbj; > char *obj; > > @@ -581,6 +584,7 @@ static void smk_rule_show(struct seq_file *s, struct smack_rule *srp, int max) > * interface file (/smack/load or /smack/load2) > * because you should expect to be able to write > * anything you read back. > + * Show only fully mapped rules in a namespace (both labels mapped). > */ > if (strlen(srp->smk_subject->smk_known) >= max || > strlen(srp->smk_object->smk_known) >= max) > @@ -589,8 +593,8 @@ static void smk_rule_show(struct seq_file *s, struct smack_rule *srp, int max) > if (srp->smk_access == 0) > return; > > - sbj = smk_find_label_name(srp->smk_subject); > - obj = smk_find_label_name(srp->smk_object); > + sbj = smk_find_label_name(srp->smk_subject, ns); > + obj = smk_find_label_name(srp->smk_object, ns); > > if (sbj == NULL || obj == NULL) > return; > @@ -785,6 +789,7 @@ static int cipso_seq_show(struct seq_file *s, void *v) > struct smack_known *skp = > list_entry_rcu(list, struct smack_known, list); > struct netlbl_lsm_catmap *cmp = skp->smk_netlabel.attr.mls.cat; > + struct user_namespace *ns = ns_of_current(); > char sep = '/'; > char *cp; > int i; > @@ -800,7 +805,7 @@ static int cipso_seq_show(struct seq_file *s, void *v) > if (strlen(skp->smk_known) >= SMK_LABELLEN) > return 0; > > - cp = smk_find_label_name(skp); > + cp = smk_find_label_name(skp, ns); > if (cp == NULL) > return 0; > > @@ -853,6 +858,7 @@ static ssize_t smk_set_cipso(struct file *file, const char __user *buf, > { > struct smack_known *skp; > struct netlbl_lsm_secattr ncats; > + struct user_namespace *ns = ns_of_current(); > char mapcatset[SMK_CIPSOLEN]; > int maplevel; > unsigned int cat; > @@ -893,7 +899,7 @@ static ssize_t smk_set_cipso(struct file *file, const char __user *buf, > */ > mutex_lock(&smack_cipso_lock); > > - skp = smk_get_label(rule, 0, true); > + skp = smk_get_label(rule, 0, true, ns); > if (IS_ERR(skp)) { > rc = PTR_ERR(skp); > goto out; > @@ -981,11 +987,12 @@ static int cipso2_seq_show(struct seq_file *s, void *v) > struct smack_known *skp = > list_entry_rcu(list, struct smack_known, list); > struct netlbl_lsm_catmap *cmp = skp->smk_netlabel.attr.mls.cat; > + struct user_namespace *ns = ns_of_current(); > char sep = '/'; > char *cp; > int i; > > - cp = smk_find_label_name(skp); > + cp = smk_find_label_name(skp, ns); > if (cp == NULL) > return 0; > > @@ -1066,12 +1073,13 @@ static void *net4addr_seq_next(struct seq_file *s, void *v, loff_t *pos) > static int net4addr_seq_show(struct seq_file *s, void *v) > { > struct list_head *list = v; > + struct user_namespace *ns = ns_of_current(); > struct smk_net4addr *skp = > list_entry_rcu(list, struct smk_net4addr, list); > char *kp = SMACK_CIPSO_OPTION; > > if (skp->smk_label != NULL) { > - kp = smk_find_label_name(skp->smk_label); > + kp = smk_find_label_name(skp->smk_label, ns); > if (kp == NULL) > kp = smack_known_huh.smk_known; > } > @@ -1167,6 +1175,7 @@ static ssize_t smk_write_net4addr(struct file *file, const char __user *buf, > int rc; > struct netlbl_audit audit_info; > struct in_addr mask; > + struct user_namespace *ns = ns_of_current(); > unsigned int m; > unsigned int masks; > int found; > @@ -1226,7 +1235,7 @@ static ssize_t smk_write_net4addr(struct file *file, const char __user *buf, > * If smack begins with '-', it is an option, don't import it > */ > if (smack[0] != '-') { > - skp = smk_get_label(smack, 0, true); > + skp = smk_get_label(smack, 0, true, ns); > if (IS_ERR(skp)) { > rc = PTR_ERR(skp); > goto free_out; > @@ -1345,10 +1354,11 @@ static int net6addr_seq_show(struct seq_file *s, void *v) > struct list_head *list = v; > struct smk_net6addr *skp = > list_entry(list, struct smk_net6addr, list); > + struct user_namespace *ns = ns_of_current(); > char *kp; > > if (skp->smk_label != NULL) { > - kp = smk_find_label_name(skp->smk_label); > + kp = smk_find_label_name(skp->smk_label, ns); > if (kp == NULL) > kp = smack_known_huh.smk_known; > > @@ -1438,6 +1448,7 @@ static ssize_t smk_write_net6addr(struct file *file, const char __user *buf, > struct in6_addr newname; > struct in6_addr fullmask; > struct smack_known *skp = NULL; > + struct user_namespace *ns = ns_of_current(); > char *smack; > char *data; > int rc = 0; > @@ -1508,7 +1519,7 @@ static ssize_t smk_write_net6addr(struct file *file, const char __user *buf, > * If smack begins with '-', it is an option, don't import it > */ > if (smack[0] != '-') { > - skp = smk_get_label(smack, 0, true); > + skp = smk_get_label(smack, 0, true, ns); > if (IS_ERR(skp)) { > rc = PTR_ERR(skp); > goto free_out; > @@ -1827,6 +1838,7 @@ static const struct file_operations smk_mapped_ops = { > static ssize_t smk_read_ambient(struct file *filp, char __user *buf, > size_t cn, loff_t *ppos) > { > + struct user_namespace *ns = ns_of_current(); > ssize_t rc = -EINVAL; > char *cp; > int asize; > @@ -1839,7 +1851,7 @@ static ssize_t smk_read_ambient(struct file *filp, char __user *buf, > */ > mutex_lock(&smack_ambient_lock); > > - cp = smk_find_label_name(smack_net_ambient); > + cp = smk_find_label_name(smack_net_ambient, ns); > if (cp == NULL) > cp = smack_known_huh.smk_known; > > @@ -1866,6 +1878,7 @@ static ssize_t smk_write_ambient(struct file *file, const char __user *buf, > size_t count, loff_t *ppos) > { > struct smack_known *skp; > + struct user_namespace *ns = ns_of_current(); > char *oldambient; > char *data; > int rc = count; > @@ -1882,7 +1895,7 @@ static ssize_t smk_write_ambient(struct file *file, const char __user *buf, > goto out; > } > > - skp = smk_get_label(data, count, true); > + skp = smk_get_label(data, count, true, ns); > if (IS_ERR(skp)) { > rc = PTR_ERR(skp); > goto out; > @@ -1923,11 +1936,12 @@ static void *onlycap_seq_next(struct seq_file *s, void *v, loff_t *pos) > static int onlycap_seq_show(struct seq_file *s, void *v) > { > char *smack; > + struct user_namespace *ns = ns_of_current(); > struct list_head *list = v; > struct smack_onlycap *sop = > list_entry_rcu(list, struct smack_onlycap, list); > > - smack = smk_find_label_name(sop->smk_label); > + smack = smk_find_label_name(sop->smk_label, ns); > if (smack == NULL) > smack = smack_known_huh.smk_known; > > @@ -2006,6 +2020,7 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf, > struct smack_onlycap *sop; > struct smack_onlycap *sop2; > LIST_HEAD(list_tmp); > + struct user_namespace *ns = ns_of_current(); > int rc = count; > > if (!smack_privileged(CAP_MAC_ADMIN)) > @@ -2025,7 +2040,7 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf, > if (!*tok) > continue; > > - skp = smk_get_label(tok, 0, true); > + skp = smk_get_label(tok, 0, true, ns); > if (IS_ERR(skp)) { > rc = PTR_ERR(skp); > break; > @@ -2091,12 +2106,13 @@ static ssize_t smk_read_unconfined(struct file *filp, char __user *buf, > char *smack = ""; > ssize_t rc = -EINVAL; > int asize; > + struct user_namespace *ns = ns_of_current(); > > if (*ppos != 0) > return 0; > > if (smack_unconfined != NULL) { > - smack = smk_find_label_name(smack_unconfined); > + smack = smk_find_label_name(smack_unconfined, ns); > if (smack == NULL) > smack = smack_known_huh.smk_known; > } > @@ -2123,6 +2139,7 @@ static ssize_t smk_write_unconfined(struct file *file, const char __user *buf, > { > char *data; > struct smack_known *skp; > + struct user_namespace *ns = ns_of_current(); > int rc = count; > > if (!smack_privileged(CAP_MAC_ADMIN)) > @@ -2146,7 +2163,7 @@ static ssize_t smk_write_unconfined(struct file *file, const char __user *buf, > * > * But do so only on invalid label, not on system errors. > */ > - skp = smk_get_label(data, count, true); > + skp = smk_get_label(data, count, true, ns); > if (PTR_ERR(skp) == -EINVAL) > skp = NULL; > else if (IS_ERR(skp)) { > @@ -2318,6 +2335,7 @@ static ssize_t smk_user_access(struct file *file, const char __user *buf, > size_t count, loff_t *ppos, int format) > { > struct smack_parsed_rule rule; > + struct user_namespace *ns = ns_of_current(); > char *data; > int res; > > @@ -2337,7 +2355,7 @@ static ssize_t smk_user_access(struct file *file, const char __user *buf, > } > > if (res >= 0) > - res = smk_access(rule.smk_subject, rule.smk_object, > + res = smk_access(rule.smk_subject, rule.smk_object, ns, > rule.smk_access1, NULL); > else if (res != -ENOENT) > return res; > @@ -2547,6 +2565,7 @@ static ssize_t smk_write_revoke_subj(struct file *file, const char __user *buf, > struct smack_rule *sp; > struct list_head *rule_list; > struct mutex *rule_lock; > + struct user_namespace *ns = ns_of_current(); > int rc = count; > > if (*ppos != 0) > @@ -2567,7 +2586,7 @@ static ssize_t smk_write_revoke_subj(struct file *file, const char __user *buf, > goto out_data; > } > > - skp = smk_get_label(data, count, false); > + skp = smk_get_label(data, count, false, ns); > if (IS_ERR(skp)) { > rc = PTR_ERR(skp); > goto out_data; > @@ -2649,12 +2668,13 @@ static ssize_t smk_read_syslog(struct file *filp, char __user *buf, > char *smack = ""; > ssize_t rc = -EINVAL; > int asize; > + struct user_namespace *ns = ns_of_current(); > > if (*ppos != 0) > return 0; > > if (smack_syslog_label != NULL) { > - smack = smk_find_label_name(smack_syslog_label); > + smack = smk_find_label_name(smack_syslog_label, ns); > if (smack == NULL) > smack = smack_known_huh.smk_known; > } > @@ -2681,6 +2701,7 @@ static ssize_t smk_write_syslog(struct file *file, const char __user *buf, > { > char *data; > struct smack_known *skp; > + struct user_namespace *ns = ns_of_current(); > int rc = count; > > if (!smack_privileged(CAP_MAC_ADMIN)) > @@ -2704,7 +2725,7 @@ static ssize_t smk_write_syslog(struct file *file, const char __user *buf, > * > * But do so only on invalid label, not on system errors. > */ > - skp = smk_get_label(data, count, true); > + skp = smk_get_label(data, count, true, ns); > if (PTR_ERR(skp) == -EINVAL) > skp = NULL; > else if (IS_ERR(skp)) { _______________________________________________ Containers mailing list Containers@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linuxfoundation.org/mailman/listinfo/containers