security: add task argument to security_capable()
Subsystems (7)
RFC v3 1/2 security: add task argument to security_capable()
This patch changes security_capable() to use explicit task argument instead of current.
Signed-off-by Vasiliy Kulikov <[email protected]>
--- drivers/pci/pci-sysfs.c | 5 ++++- include/linux/security.h | 8 ++++---- kernel/capability.c | 2 +- security/security.c | 6 +++--- 4 files changed, 12 insertions(+), 9 deletions(-)
drivers/pci/pci-sysfs.c +4 -1
@@ -431,7 +431,10 @@ pci_read_config(struct file *filp, struct kobject *kobj,u8 *data = (u8 *) buf;/* Several chips lock up trying to read undefined config space */ -if (security_capable (&init_user_ns, filp->f_cred,CAP_SYS_ADMIN ) ==0 ) { +if (security_capable (current, + &init_user_ns, + filp->f_cred, +CAP_SYS_ADMIN ) ==0 ) { size = dev->cfg_size; }else if (dev->hdr_type ==PCI_HEADER_TYPE_CARDBUS ) { size =128 ;
include/linux/security.h +4 -4
@@ -1667,8 +1667,8 @@ int security_capset(struct cred *new, const struct cred *old,const kernel_cap_t *effective, const kernel_cap_t *inheritable, const kernel_cap_t *permitted); -int security_capable (struct user_namespace *ns,const struct cred *cred, -int cap); +int security_capable (struct task_struct *task,struct user_namespace *ns, +const struct cred *cred,int cap);int security_real_capable (struct task_struct *tsk,struct user_namespace *ns,int cap); int security_real_capable_noaudit(struct task_struct *tsk,
@@ -1865,10 +1865,10 @@ static inline int security_capset(struct cred *new,return cap_capset (new, old, effective, inheritable, permitted); } -static inline int security_capable (struct user_namespace *ns, +static inline int security_capable (struct task_struct *task,struct user_namespace *ns,const struct cred *cred,int cap) { -return cap_capable (current, cred, ns, cap,SECURITY_CAP_AUDIT ); +return cap_capable (task, cred, ns, cap,SECURITY_CAP_AUDIT ); }static inline int security_real_capable (struct task_struct *tsk,struct user_namespace *ns,int cap)
kernel/capability.c +1 -1
@@ -374,7 +374,7 @@ bool ns_capable(struct user_namespace *ns, int cap)BUG (); } -if (security_capable (ns,current_cred (), cap) ==0 ) { +if (security_capable (current, ns,current_cred (), cap) ==0 ) { current->flags |=PF_SUPERPRIV ;return true; }
security/security.c +3 -3
@@ -154,10 +154,10 @@ int security_capset(struct cred *new, const struct cred *old, effective, inheritable, permitted); } -int security_capable (struct user_namespace *ns,const struct cred *cred, -int cap) +int security_capable (struct task_struct *task,struct user_namespace *ns, +const struct cred *cred,int cap) { -return security_ops->capable (current, cred, ns, cap, +return security_ops->capable (task, cred, ns, cap,SECURITY_CAP_AUDIT ); }
---
RFC v3 2/2 security: add ptrace_task_may_access_current()
ptrace_task_may_access_current() is needed to check whether another process may ptrace current. LSM hook and related functions now have "tracer" as the first argument instead of implicit "current".
Signed-off-by Vasiliy Kulikov <[email protected]>
--- include/linux/ptrace.h | 6 +++++- include/linux/security.h | 22 +++++++++++++++------- kernel/ptrace.c | 30 ++++++++++++++++++++++-------- security/apparmor/lsm.c | 7 ++++--- security/commoncap.c | 8 +++++--- security/security.c | 6 ++++-- security/selinux/hooks.c | 11 ++++++----- security/smack/smack.h | 1 + security/smack/smack_access.c | 15 +++++++++++---- security/smack/smack_lsm.c | 9 ++++++--- 10 files changed, 79 insertions(+), 36 deletions(-)
include/linux/ptrace.h +5 -1
@@ -116,9 +116,13 @@ extern void exit_ptrace(struct task_struct *tracer);#define PTRACE_MODE_READ 1#define PTRACE_MODE_ATTACH 2/* Returns 0 on success, -errno on denial. */ -extern int __ptrace_may_access (struct task_struct *task,unsigned int mode); +extern int __ptrace_may_access (struct task_struct *tracer, +struct task_struct *task, +unsigned int mode);/* Returns true on success, false on denial. */ extern bool ptrace_may_access (struct task_struct *task,unsigned int mode); +extern bool ptrace_task_may_access_current (struct task_struct *task, +unsigned int mode);static inline int ptrace_reparented (struct task_struct *child) {
include/linux/security.h +15 -7
@@ -56,7 +56,9 @@ struct user_namespace;extern int cap_capable (struct task_struct *tsk,const struct cred *cred,struct user_namespace *ns,int cap,int audit);extern int cap_settime (const struct timespec *ts,const struct timezone *tz); -extern int cap_ptrace_access_check (struct task_struct *child,unsigned int mode); +extern int cap_ptrace_access_check (struct task_struct *tracer, +struct task_struct *child, +unsigned int mode);extern int cap_ptrace_traceme (struct task_struct *parent);extern int cap_capget (struct task_struct *target,kernel_cap_t *effective,kernel_cap_t *inheritable,kernel_cap_t *permitted); extern int cap_capset(struct cred *new, const struct cred *old,
@@ -1221,13 +1223,14 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)* Return 0 if permission is granted. * * @ptrace_access_check: -* Check permission before allowing the current process to trace the +* Check permission before allowing the @tracer process to trace the * @child process. * Security modules may also want to perform a process tracing check * during an execve in the set_security or apply_creds hooks of * tracing check during an execve in the bprm_set_creds hook of * binprm_security_ops if the process is being traced and its security * attributes would be changed by the execve. +* @tracer contains the task_struct structure for the tracer process. * @child contains the task_struct structure for the target process. * @mode contains the PTRACE_MODE flags indicating the form of access. * Return 0 if permission is granted.
@@ -1375,7 +1378,9 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)struct security_operations {char name[SECURITY_NAME_MAX +1 ]; -int (*ptrace_access_check) (struct task_struct *child,unsigned int mode); +int (*ptrace_access_check) (struct task_struct *tracer, +struct task_struct *child, +unsigned int mode);int (*ptrace_traceme) (struct task_struct *parent); int (*capget) (struct task_struct *target, kernel_cap_t *effective,
@@ -1657,7 +1662,9 @@ extern int security_module_enable(struct security_operations *ops);extern int register_security (struct security_operations *ops);/* Security operations */ -int security_ptrace_access_check (struct task_struct *child,unsigned int mode); +int security_ptrace_access_check (struct task_struct *tracer, +struct task_struct *child, +unsigned int mode);int security_ptrace_traceme (struct task_struct *parent); int security_capget(struct task_struct *target, kernel_cap_t *effective,
@@ -1837,10 +1844,11 @@ static inline int security_init(void)return 0 ; } -static inline int security_ptrace_access_check (struct task_struct *child, -unsigned int mode) +static inline int security_ptrace_access_check (struct task_struct *tracer, +struct task_struct *child, +unsigned int mode) { -return cap_ptrace_access_check (child, mode); +return cap_ptrace_access_check (tracer, child, mode); }static inline int security_ptrace_traceme (struct task_struct *parent)
kernel/ptrace.c +22 -8
@@ -132,9 +132,11 @@ int ptrace_check_attach(struct task_struct *child, int kill)return ret; } -int __ptrace_may_access (struct task_struct *task,unsigned int mode) +int __ptrace_may_access (struct task_struct *tracer, +struct task_struct *task, +unsigned int mode) { -const struct cred *cred =current_cred (), *tcred; +const struct cred *cred, *tcred;/* May we inspect the given task? * This check is used both for attaching with ptrace
@@ -146,9 +148,10 @@ int __ptrace_may_access(struct task_struct *task, unsigned int mode)*/ int dumpable =0 ;/* Don't let security modules deny introspection */ -if (task == current) +if (task == tracer)return 0 ;rcu_read_lock (); + cred =__task_cred (tracer); tcred =__task_cred (task); if (cred->user->user_ns == tcred->user->user_ns && (cred->uid == tcred->euid &&
@@ -158,7 +161,7 @@ int __ptrace_may_access(struct task_struct *task, unsigned int mode) cred->gid == tcred->sgid && cred->gid == tcred->gid)) goto ok; -if (ns_capable (tcred->user->user_ns,CAP_SYS_PTRACE )) +if (has_ns_capability (tracer, tcred->user->user_ns,CAP_SYS_PTRACE )) goto ok;rcu_read_unlock ();return -EPERM ;
@@ -167,17 +170,28 @@ ok:smp_rmb ();if (task->mm) dumpable =get_dumpable (task->mm); -if (!dumpable && !task_ns_capable (task,CAP_SYS_PTRACE )) +if (!dumpable && !has_ns_capability (tracer, +task_cred_xxx (task, user)->user_ns, +CAP_SYS_PTRACE ))return -EPERM ; -return security_ptrace_access_check (task, mode); +return security_ptrace_access_check (tracer, task, mode); }bool ptrace_may_access (struct task_struct *task,unsigned int mode) {int err;task_lock (task); - err =__ptrace_may_access (task, mode); + err =__ptrace_may_access (current, task, mode); +task_unlock (task); +return !err; +} + +bool ptrace_task_may_access_current (struct task_struct *task,unsigned int mode) +{ +int err; +task_lock (task); + err =__ptrace_may_access (task, current, mode);task_unlock (task);return !err; }
@@ -205,7 +219,7 @@ static int ptrace_attach(struct task_struct *task) goto out;task_lock (task); - retval =__ptrace_may_access (task,PTRACE_MODE_ATTACH ); + retval =__ptrace_may_access (current, task,PTRACE_MODE_ATTACH );task_unlock (task);if (retval) goto unlock_creds;
security/apparmor/lsm.c +4 -3
@@ -93,14 +93,15 @@ static void apparmor_cred_transfer(struct cred *new, const struct cred *old)aa_dup_task_context (new_cxt, old_cxt); } -static int apparmor_ptrace_access_check (struct task_struct *child, +static int apparmor_ptrace_access_check (struct task_struct *tracer, +struct task_struct *child,unsigned int mode) { -int error =cap_ptrace_access_check (child, mode); +int error =cap_ptrace_access_check (tracer, child, mode);if (error)return error; -return aa_ptrace (current, child, mode); +return aa_ptrace (tracer, child, mode); }static int apparmor_ptrace_traceme (struct task_struct *parent)
security/commoncap.c +5 -3
@@ -136,18 +136,20 @@ int cap_settime(const struct timespec *ts, const struct timezone *tz)* Determine whether a process may access another, returning 0 if permission * granted, -ve if denied. */ -int cap_ptrace_access_check (struct task_struct *child,unsigned int mode) +int cap_ptrace_access_check (struct task_struct *tracer, +struct task_struct *child, +unsigned int mode) {int ret =0 ;const struct cred *cred, *child_cred;rcu_read_lock (); - cred =current_cred (); + cred =__task_cred (tracer); child_cred =__task_cred (child);if (cred->user->user_ns == child_cred->user->user_ns &&cap_issubset (child_cred->cap_permitted, cred->cap_permitted)) goto out; -if (ns_capable (child_cred->user->user_ns,CAP_SYS_PTRACE )) +if (has_ns_capability (tracer, child_cred->user->user_ns,CAP_SYS_PTRACE )) goto out; ret = -EPERM ; out:
security/security.c +4 -2
@@ -127,9 +127,11 @@ int __init register_security(struct security_operations *ops)/* Security operations */ -int security_ptrace_access_check (struct task_struct *child,unsigned int mode) +int security_ptrace_access_check (struct task_struct *tracer, +struct task_struct *child, +unsigned int mode) { -return security_ops->ptrace_access_check (child, mode); +return security_ops->ptrace_access_check (tracer, child, mode); }int security_ptrace_traceme (struct task_struct *parent)
security/selinux/hooks.c +6 -5
@@ -1800,22 +1800,23 @@ static inline u32 open_file_to_av(struct file *file)/* Hook functions begin here. */ -static int selinux_ptrace_access_check (struct task_struct *child, -unsigned int mode) +static int selinux_ptrace_access_check (struct task_struct *tracer, +struct task_struct *child, +unsigned int mode) {int rc; - rc =cap_ptrace_access_check (child, mode); + rc =cap_ptrace_access_check (tracer, child, mode);if (rc)return rc;if (mode ==PTRACE_MODE_READ ) { -u32 sid =current_sid (); +u32 sid =task_sid (tracer);u32 csid =task_sid (child);return avc_has_perm (sid, csid,SECCLASS_FILE ,FILE__READ ,NULL ); } -return current_has_perm (child,PROCESS__PTRACE ); +return task_has_perm (tracer, child,PROCESS__PTRACE ); }static int selinux_ptrace_traceme (struct task_struct *parent)
security/smack/smack.h +1 -0
@@ -200,6 +200,7 @@ struct inode_smack *new_inode_smack(char *);int smk_access_entry (char *,char *,struct list_head *);int smk_access (char *,char *,int ,struct smk_audit_info *);int smk_curacc (char *,u32 ,struct smk_audit_info *); +int smk_taskacc (struct task_struct *task,char *,u32 ,struct smk_audit_info *);int smack_to_cipso (const char *,struct smack_cipso *);void smack_from_cipso (u32 ,char *,char *);char *smack_from_secid (const u32 );
security/smack/smack_access.c +11 -4
@@ -201,7 +201,8 @@ out_audit: }/** -* smk_curacc - determine if current has a specific access to an object +* smk_taskacc - determine if task has a specific access to an object +* @task: a pointer to the subject's task struct * @obj_label: a pointer to the object's Smack label * @mode: the access requested, in "MAY" format * @a : common audit data
@@ -211,9 +212,10 @@ out_audit:* non zero otherwise. It allows that current may have the capability * to override the rules. */ -int smk_curacc (char *obj_label,u32 mode,struct smk_audit_info *a) +int smk_taskacc (struct task_struct *task,char *obj_label, +u32 mode,struct smk_audit_info *a) { -struct task_smack *tsp =current_security (); +struct task_smack *tsp =task_cred_xxx (task, security);char *sp =smk_of_task (tsp);int may;int rc;
@@ -243,7 +245,7 @@ int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a)if (smack_onlycap !=NULL && smack_onlycap != sp) goto out_audit; -if (capable (CAP_MAC_OVERRIDE )) +if (has_capability (task,CAP_MAC_OVERRIDE )) rc =0 ; out_audit:
@@ -254,6 +256,11 @@ out_audit:return rc; } +int smk_curacc (char *obj_label,u32 mode,struct smk_audit_info *a) +{ +return smk_taskacc (current, obj_label, mode, a); +} +#ifdef CONFIG_AUDIT /** * smack_str_from_perm : helper to transalate an int to a
security/smack/smack_lsm.c +6 -3
@@ -142,6 +142,7 @@ static int smk_copy_rules(struct list_head *nhead, struct list_head *ohead,/** * smack_ptrace_access_check - Smack approval on PTRACE_ATTACH +* @ttp: tracer task pointer * @ctp: child task pointer * @mode: ptrace attachment mode *
@@ -149,13 +150,15 @@ static int smk_copy_rules(struct list_head *nhead, struct list_head *ohead,* * Do the capability checks, and require read and write. */ -static int smack_ptrace_access_check (struct task_struct *ctp,unsigned int mode) +static int smack_ptrace_access_check (struct task_struct *ttp, +struct task_struct *ctp, +unsigned int mode) {int rc;struct smk_audit_info ad;char *tsp; - rc =cap_ptrace_access_check (ctp, mode); + rc =cap_ptrace_access_check (ttp, ctp, mode);if (rc !=0 )return rc;
@@ -163,7 +166,7 @@ static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode)smk_ad_init (&ad, __func__,LSM_AUDIT_DATA_TASK );smk_ad_setfield_u_tsk (&ad, ctp); - rc =smk_curacc (tsp,MAY_READWRITE , &ad); + rc =smk_taskacc (ttp, tsp,MAY_READWRITE , &ad);return rc; }
---