diff options
author | Lukasz Pawelczyk <l.pawelczyk@partner.samsung.com> | 2014-03-11 12:07:05 -0400 |
---|---|---|
committer | Casey Schaufler <casey@schaufler-ca.com> | 2014-04-11 17:34:26 -0400 |
commit | 5663884caab166f87ab8c68ec7c62b1cce85a400 (patch) | |
tree | a106c1314669cbe6809f2b327395f0d37167b10f | |
parent | 959e6c7f1eee42f14d31755b1134f5615db1d9bc (diff) |
Smack: unify all ptrace accesses in the smack
The decision whether we can trace a process is made in the following
functions:
smack_ptrace_traceme()
smack_ptrace_access_check()
smack_bprm_set_creds() (in case the proces is traced)
This patch unifies all those decisions by introducing one function that
checks whether ptrace is allowed: smk_ptrace_rule_check().
This makes possible to actually trace with TRACEME where first the
TRACEME itself must be allowed and then exec() on a traced process.
Additional bugs fixed:
- The decision is made according to the mode parameter that is now correctly
translated from PTRACE_MODE_* to MAY_* instead of being treated 1:1.
PTRACE_MODE_READ requires MAY_READ.
PTRACE_MODE_ATTACH requires MAY_READWRITE.
- Add a smack audit log in case of exec() refused by bprm_set_creds().
- Honor the PTRACE_MODE_NOAUDIT flag and don't put smack audit info
in case this flag is set.
Signed-off-by: Lukasz Pawelczyk <l.pawelczyk@partner.samsung.com>
Signed-off-by: Rafal Krypa <r.krypa@samsung.com>
-rw-r--r-- | security/smack/smack_lsm.c | 84 |
1 files changed, 71 insertions, 13 deletions
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index b23fbdd4cdad..4d6f37644baa 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
@@ -157,6 +157,54 @@ static int smk_copy_rules(struct list_head *nhead, struct list_head *ohead, | |||
157 | return rc; | 157 | return rc; |
158 | } | 158 | } |
159 | 159 | ||
160 | /** | ||
161 | * smk_ptrace_mode - helper function for converting PTRACE_MODE_* into MAY_* | ||
162 | * @mode - input mode in form of PTRACE_MODE_* | ||
163 | * | ||
164 | * Returns a converted MAY_* mode usable by smack rules | ||
165 | */ | ||
166 | static inline unsigned int smk_ptrace_mode(unsigned int mode) | ||
167 | { | ||
168 | switch (mode) { | ||
169 | case PTRACE_MODE_READ: | ||
170 | return MAY_READ; | ||
171 | case PTRACE_MODE_ATTACH: | ||
172 | return MAY_READWRITE; | ||
173 | } | ||
174 | |||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | /** | ||
179 | * smk_ptrace_rule_check - helper for ptrace access | ||
180 | * @tracer: tracer process | ||
181 | * @tracee_label: label of the process that's about to be traced | ||
182 | * @mode: ptrace attachment mode (PTRACE_MODE_*) | ||
183 | * @func: name of the function that called us, used for audit | ||
184 | * | ||
185 | * Returns 0 on access granted, -error on error | ||
186 | */ | ||
187 | static int smk_ptrace_rule_check(struct task_struct *tracer, char *tracee_label, | ||
188 | unsigned int mode, const char *func) | ||
189 | { | ||
190 | int rc; | ||
191 | struct smk_audit_info ad, *saip = NULL; | ||
192 | struct task_smack *tsp; | ||
193 | struct smack_known *skp; | ||
194 | |||
195 | if ((mode & PTRACE_MODE_NOAUDIT) == 0) { | ||
196 | smk_ad_init(&ad, func, LSM_AUDIT_DATA_TASK); | ||
197 | smk_ad_setfield_u_tsk(&ad, tracer); | ||
198 | saip = &ad; | ||
199 | } | ||
200 | |||
201 | tsp = task_security(tracer); | ||
202 | skp = smk_of_task(tsp); | ||
203 | |||
204 | rc = smk_tskacc(tsp, tracee_label, smk_ptrace_mode(mode), saip); | ||
205 | return rc; | ||
206 | } | ||
207 | |||
160 | /* | 208 | /* |
161 | * LSM hooks. | 209 | * LSM hooks. |
162 | * We he, that is fun! | 210 | * We he, that is fun! |
@@ -165,16 +213,15 @@ static int smk_copy_rules(struct list_head *nhead, struct list_head *ohead, | |||
165 | /** | 213 | /** |
166 | * smack_ptrace_access_check - Smack approval on PTRACE_ATTACH | 214 | * smack_ptrace_access_check - Smack approval on PTRACE_ATTACH |
167 | * @ctp: child task pointer | 215 | * @ctp: child task pointer |
168 | * @mode: ptrace attachment mode | 216 | * @mode: ptrace attachment mode (PTRACE_MODE_*) |
169 | * | 217 | * |
170 | * Returns 0 if access is OK, an error code otherwise | 218 | * Returns 0 if access is OK, an error code otherwise |
171 | * | 219 | * |
172 | * Do the capability checks, and require read and write. | 220 | * Do the capability checks. |
173 | */ | 221 | */ |
174 | static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode) | 222 | static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode) |
175 | { | 223 | { |
176 | int rc; | 224 | int rc; |
177 | struct smk_audit_info ad; | ||
178 | struct smack_known *skp; | 225 | struct smack_known *skp; |
179 | 226 | ||
180 | rc = cap_ptrace_access_check(ctp, mode); | 227 | rc = cap_ptrace_access_check(ctp, mode); |
@@ -182,10 +229,8 @@ static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode) | |||
182 | return rc; | 229 | return rc; |
183 | 230 | ||
184 | skp = smk_of_task(task_security(ctp)); | 231 | skp = smk_of_task(task_security(ctp)); |
185 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); | ||
186 | smk_ad_setfield_u_tsk(&ad, ctp); | ||
187 | 232 | ||
188 | rc = smk_curacc(skp->smk_known, mode, &ad); | 233 | rc = smk_ptrace_rule_check(current, skp->smk_known, mode, __func__); |
189 | return rc; | 234 | return rc; |
190 | } | 235 | } |
191 | 236 | ||
@@ -195,12 +240,11 @@ static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode) | |||
195 | * | 240 | * |
196 | * Returns 0 if access is OK, an error code otherwise | 241 | * Returns 0 if access is OK, an error code otherwise |
197 | * | 242 | * |
198 | * Do the capability checks, and require read and write. | 243 | * Do the capability checks, and require PTRACE_MODE_ATTACH. |
199 | */ | 244 | */ |
200 | static int smack_ptrace_traceme(struct task_struct *ptp) | 245 | static int smack_ptrace_traceme(struct task_struct *ptp) |
201 | { | 246 | { |
202 | int rc; | 247 | int rc; |
203 | struct smk_audit_info ad; | ||
204 | struct smack_known *skp; | 248 | struct smack_known *skp; |
205 | 249 | ||
206 | rc = cap_ptrace_traceme(ptp); | 250 | rc = cap_ptrace_traceme(ptp); |
@@ -208,10 +252,9 @@ static int smack_ptrace_traceme(struct task_struct *ptp) | |||
208 | return rc; | 252 | return rc; |
209 | 253 | ||
210 | skp = smk_of_task(current_security()); | 254 | skp = smk_of_task(current_security()); |
211 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); | ||
212 | smk_ad_setfield_u_tsk(&ad, ptp); | ||
213 | 255 | ||
214 | rc = smk_tskacc(ptp, skp->smk_known, MAY_READWRITE, &ad); | 256 | rc = smk_ptrace_rule_check(ptp, skp->smk_known, |
257 | PTRACE_MODE_ATTACH, __func__); | ||
215 | return rc; | 258 | return rc; |
216 | } | 259 | } |
217 | 260 | ||
@@ -455,7 +498,7 @@ static int smack_sb_statfs(struct dentry *dentry) | |||
455 | * smack_bprm_set_creds - set creds for exec | 498 | * smack_bprm_set_creds - set creds for exec |
456 | * @bprm: the exec information | 499 | * @bprm: the exec information |
457 | * | 500 | * |
458 | * Returns 0 if it gets a blob, -ENOMEM otherwise | 501 | * Returns 0 if it gets a blob, -EPERM if exec forbidden and -ENOMEM otherwise |
459 | */ | 502 | */ |
460 | static int smack_bprm_set_creds(struct linux_binprm *bprm) | 503 | static int smack_bprm_set_creds(struct linux_binprm *bprm) |
461 | { | 504 | { |
@@ -475,7 +518,22 @@ static int smack_bprm_set_creds(struct linux_binprm *bprm) | |||
475 | if (isp->smk_task == NULL || isp->smk_task == bsp->smk_task) | 518 | if (isp->smk_task == NULL || isp->smk_task == bsp->smk_task) |
476 | return 0; | 519 | return 0; |
477 | 520 | ||
478 | if (bprm->unsafe) | 521 | if (bprm->unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) { |
522 | struct task_struct *tracer; | ||
523 | rc = 0; | ||
524 | |||
525 | rcu_read_lock(); | ||
526 | tracer = ptrace_parent(current); | ||
527 | if (likely(tracer != NULL)) | ||
528 | rc = smk_ptrace_rule_check(tracer, | ||
529 | isp->smk_task->smk_known, | ||
530 | PTRACE_MODE_ATTACH, | ||
531 | __func__); | ||
532 | rcu_read_unlock(); | ||
533 | |||
534 | if (rc != 0) | ||
535 | return rc; | ||
536 | } else if (bprm->unsafe) | ||
479 | return -EPERM; | 537 | return -EPERM; |
480 | 538 | ||
481 | bsp->smk_task = isp->smk_task; | 539 | bsp->smk_task = isp->smk_task; |