aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/capability.c19
-rw-r--r--security/commoncap.c152
-rw-r--r--security/keys/process_keys.c42
-rw-r--r--security/root_plug.c13
-rw-r--r--security/security.c26
-rw-r--r--security/selinux/hooks.c283
-rw-r--r--security/selinux/include/objsec.h11
-rw-r--r--security/smack/smack_lsm.c3
8 files changed, 214 insertions, 335 deletions
diff --git a/security/capability.c b/security/capability.c
index efeb6d9e0e6a..185804f99ad1 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -32,24 +32,19 @@ static int cap_quota_on(struct dentry *dentry)
32 return 0; 32 return 0;
33} 33}
34 34
35static int cap_bprm_alloc_security(struct linux_binprm *bprm) 35static int cap_bprm_check_security (struct linux_binprm *bprm)
36{ 36{
37 return 0; 37 return 0;
38} 38}
39 39
40static void cap_bprm_free_security(struct linux_binprm *bprm) 40static void cap_bprm_committing_creds(struct linux_binprm *bprm)
41{ 41{
42} 42}
43 43
44static void cap_bprm_post_apply_creds(struct linux_binprm *bprm) 44static void cap_bprm_committed_creds(struct linux_binprm *bprm)
45{ 45{
46} 46}
47 47
48static int cap_bprm_check_security(struct linux_binprm *bprm)
49{
50 return 0;
51}
52
53static int cap_sb_alloc_security(struct super_block *sb) 48static int cap_sb_alloc_security(struct super_block *sb)
54{ 49{
55 return 0; 50 return 0;
@@ -827,11 +822,9 @@ void security_fixup_ops(struct security_operations *ops)
827 set_to_cap_if_null(ops, syslog); 822 set_to_cap_if_null(ops, syslog);
828 set_to_cap_if_null(ops, settime); 823 set_to_cap_if_null(ops, settime);
829 set_to_cap_if_null(ops, vm_enough_memory); 824 set_to_cap_if_null(ops, vm_enough_memory);
830 set_to_cap_if_null(ops, bprm_alloc_security); 825 set_to_cap_if_null(ops, bprm_set_creds);
831 set_to_cap_if_null(ops, bprm_free_security); 826 set_to_cap_if_null(ops, bprm_committing_creds);
832 set_to_cap_if_null(ops, bprm_apply_creds); 827 set_to_cap_if_null(ops, bprm_committed_creds);
833 set_to_cap_if_null(ops, bprm_post_apply_creds);
834 set_to_cap_if_null(ops, bprm_set_security);
835 set_to_cap_if_null(ops, bprm_check_security); 828 set_to_cap_if_null(ops, bprm_check_security);
836 set_to_cap_if_null(ops, bprm_secureexec); 829 set_to_cap_if_null(ops, bprm_secureexec);
837 set_to_cap_if_null(ops, sb_alloc_security); 830 set_to_cap_if_null(ops, sb_alloc_security);
diff --git a/security/commoncap.c b/security/commoncap.c
index b5419273f92d..51dfa11e8e56 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -167,7 +167,7 @@ int cap_capset(struct cred *new,
167 167
168static inline void bprm_clear_caps(struct linux_binprm *bprm) 168static inline void bprm_clear_caps(struct linux_binprm *bprm)
169{ 169{
170 cap_clear(bprm->cap_post_exec_permitted); 170 cap_clear(bprm->cred->cap_permitted);
171 bprm->cap_effective = false; 171 bprm->cap_effective = false;
172} 172}
173 173
@@ -198,15 +198,15 @@ int cap_inode_killpriv(struct dentry *dentry)
198} 198}
199 199
200static inline int bprm_caps_from_vfs_caps(struct cpu_vfs_cap_data *caps, 200static inline int bprm_caps_from_vfs_caps(struct cpu_vfs_cap_data *caps,
201 struct linux_binprm *bprm) 201 struct linux_binprm *bprm,
202 bool *effective)
202{ 203{
204 struct cred *new = bprm->cred;
203 unsigned i; 205 unsigned i;
204 int ret = 0; 206 int ret = 0;
205 207
206 if (caps->magic_etc & VFS_CAP_FLAGS_EFFECTIVE) 208 if (caps->magic_etc & VFS_CAP_FLAGS_EFFECTIVE)
207 bprm->cap_effective = true; 209 *effective = true;
208 else
209 bprm->cap_effective = false;
210 210
211 CAP_FOR_EACH_U32(i) { 211 CAP_FOR_EACH_U32(i) {
212 __u32 permitted = caps->permitted.cap[i]; 212 __u32 permitted = caps->permitted.cap[i];
@@ -215,16 +215,13 @@ static inline int bprm_caps_from_vfs_caps(struct cpu_vfs_cap_data *caps,
215 /* 215 /*
216 * pP' = (X & fP) | (pI & fI) 216 * pP' = (X & fP) | (pI & fI)
217 */ 217 */
218 bprm->cap_post_exec_permitted.cap[i] = 218 new->cap_permitted.cap[i] =
219 (current->cred->cap_bset.cap[i] & permitted) | 219 (new->cap_bset.cap[i] & permitted) |
220 (current->cred->cap_inheritable.cap[i] & inheritable); 220 (new->cap_inheritable.cap[i] & inheritable);
221 221
222 if (permitted & ~bprm->cap_post_exec_permitted.cap[i]) { 222 if (permitted & ~new->cap_permitted.cap[i])
223 /* 223 /* insufficient to execute correctly */
224 * insufficient to execute correctly
225 */
226 ret = -EPERM; 224 ret = -EPERM;
227 }
228 } 225 }
229 226
230 /* 227 /*
@@ -232,7 +229,7 @@ static inline int bprm_caps_from_vfs_caps(struct cpu_vfs_cap_data *caps,
232 * do not have enough capabilities, we return an error if they are 229 * do not have enough capabilities, we return an error if they are
233 * missing some "forced" (aka file-permitted) capabilities. 230 * missing some "forced" (aka file-permitted) capabilities.
234 */ 231 */
235 return bprm->cap_effective ? ret : 0; 232 return *effective ? ret : 0;
236} 233}
237 234
238int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps) 235int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps)
@@ -250,10 +247,9 @@ int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data
250 247
251 size = inode->i_op->getxattr((struct dentry *)dentry, XATTR_NAME_CAPS, &caps, 248 size = inode->i_op->getxattr((struct dentry *)dentry, XATTR_NAME_CAPS, &caps,
252 XATTR_CAPS_SZ); 249 XATTR_CAPS_SZ);
253 if (size == -ENODATA || size == -EOPNOTSUPP) { 250 if (size == -ENODATA || size == -EOPNOTSUPP)
254 /* no data, that's ok */ 251 /* no data, that's ok */
255 return -ENODATA; 252 return -ENODATA;
256 }
257 if (size < 0) 253 if (size < 0)
258 return size; 254 return size;
259 255
@@ -262,7 +258,7 @@ int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data
262 258
263 cpu_caps->magic_etc = magic_etc = le32_to_cpu(caps.magic_etc); 259 cpu_caps->magic_etc = magic_etc = le32_to_cpu(caps.magic_etc);
264 260
265 switch ((magic_etc & VFS_CAP_REVISION_MASK)) { 261 switch (magic_etc & VFS_CAP_REVISION_MASK) {
266 case VFS_CAP_REVISION_1: 262 case VFS_CAP_REVISION_1:
267 if (size != XATTR_CAPS_SZ_1) 263 if (size != XATTR_CAPS_SZ_1)
268 return -EINVAL; 264 return -EINVAL;
@@ -283,11 +279,12 @@ int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data
283 cpu_caps->permitted.cap[i] = le32_to_cpu(caps.data[i].permitted); 279 cpu_caps->permitted.cap[i] = le32_to_cpu(caps.data[i].permitted);
284 cpu_caps->inheritable.cap[i] = le32_to_cpu(caps.data[i].inheritable); 280 cpu_caps->inheritable.cap[i] = le32_to_cpu(caps.data[i].inheritable);
285 } 281 }
282
286 return 0; 283 return 0;
287} 284}
288 285
289/* Locate any VFS capabilities: */ 286/* Locate any VFS capabilities: */
290static int get_file_caps(struct linux_binprm *bprm) 287static int get_file_caps(struct linux_binprm *bprm, bool *effective)
291{ 288{
292 struct dentry *dentry; 289 struct dentry *dentry;
293 int rc = 0; 290 int rc = 0;
@@ -313,7 +310,10 @@ static int get_file_caps(struct linux_binprm *bprm)
313 goto out; 310 goto out;
314 } 311 }
315 312
316 rc = bprm_caps_from_vfs_caps(&vcaps, bprm); 313 rc = bprm_caps_from_vfs_caps(&vcaps, bprm, effective);
314 if (rc == -EINVAL)
315 printk(KERN_NOTICE "%s: cap_from_disk returned %d for %s\n",
316 __func__, rc, bprm->filename);
317 317
318out: 318out:
319 dput(dentry); 319 dput(dentry);
@@ -334,18 +334,27 @@ int cap_inode_killpriv(struct dentry *dentry)
334 return 0; 334 return 0;
335} 335}
336 336
337static inline int get_file_caps(struct linux_binprm *bprm) 337static inline int get_file_caps(struct linux_binprm *bprm, bool *effective)
338{ 338{
339 bprm_clear_caps(bprm); 339 bprm_clear_caps(bprm);
340 return 0; 340 return 0;
341} 341}
342#endif 342#endif
343 343
344int cap_bprm_set_security (struct linux_binprm *bprm) 344/*
345 * set up the new credentials for an exec'd task
346 */
347int cap_bprm_set_creds(struct linux_binprm *bprm)
345{ 348{
349 const struct cred *old = current_cred();
350 struct cred *new = bprm->cred;
351 bool effective;
346 int ret; 352 int ret;
347 353
348 ret = get_file_caps(bprm); 354 effective = false;
355 ret = get_file_caps(bprm, &effective);
356 if (ret < 0)
357 return ret;
349 358
350 if (!issecure(SECURE_NOROOT)) { 359 if (!issecure(SECURE_NOROOT)) {
351 /* 360 /*
@@ -353,63 +362,47 @@ int cap_bprm_set_security (struct linux_binprm *bprm)
353 * executables under compatibility mode, we override the 362 * executables under compatibility mode, we override the
354 * capability sets for the file. 363 * capability sets for the file.
355 * 364 *
356 * If only the real uid is 0, we do not set the effective 365 * If only the real uid is 0, we do not set the effective bit.
357 * bit.
358 */ 366 */
359 if (bprm->e_uid == 0 || current_uid() == 0) { 367 if (new->euid == 0 || new->uid == 0) {
360 /* pP' = (cap_bset & ~0) | (pI & ~0) */ 368 /* pP' = (cap_bset & ~0) | (pI & ~0) */
361 bprm->cap_post_exec_permitted = cap_combine( 369 new->cap_permitted = cap_combine(old->cap_bset,
362 current->cred->cap_bset, 370 old->cap_inheritable);
363 current->cred->cap_inheritable);
364 bprm->cap_effective = (bprm->e_uid == 0);
365 ret = 0;
366 } 371 }
372 if (new->euid == 0)
373 effective = true;
367 } 374 }
368 375
369 return ret; 376 /* Don't let someone trace a set[ug]id/setpcap binary with the revised
370} 377 * credentials unless they have the appropriate permit
371 378 */
372int cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe) 379 if ((new->euid != old->uid ||
373{ 380 new->egid != old->gid ||
374 const struct cred *old = current_cred(); 381 !cap_issubset(new->cap_permitted, old->cap_permitted)) &&
375 struct cred *new; 382 bprm->unsafe & ~LSM_UNSAFE_PTRACE_CAP) {
376 383 /* downgrade; they get no more than they had, and maybe less */
377 new = prepare_creds(); 384 if (!capable(CAP_SETUID)) {
378 if (!new) 385 new->euid = new->uid;
379 return -ENOMEM; 386 new->egid = new->gid;
380
381 if (bprm->e_uid != old->uid || bprm->e_gid != old->gid ||
382 !cap_issubset(bprm->cap_post_exec_permitted,
383 old->cap_permitted)) {
384 set_dumpable(current->mm, suid_dumpable);
385 current->pdeath_signal = 0;
386
387 if (unsafe & ~LSM_UNSAFE_PTRACE_CAP) {
388 if (!capable(CAP_SETUID)) {
389 bprm->e_uid = old->uid;
390 bprm->e_gid = old->gid;
391 }
392 if (cap_limit_ptraced_target()) {
393 bprm->cap_post_exec_permitted = cap_intersect(
394 bprm->cap_post_exec_permitted,
395 new->cap_permitted);
396 }
397 } 387 }
388 if (cap_limit_ptraced_target())
389 new->cap_permitted = cap_intersect(new->cap_permitted,
390 old->cap_permitted);
398 } 391 }
399 392
400 new->suid = new->euid = new->fsuid = bprm->e_uid; 393 new->suid = new->fsuid = new->euid;
401 new->sgid = new->egid = new->fsgid = bprm->e_gid; 394 new->sgid = new->fsgid = new->egid;
402 395
403 /* For init, we want to retain the capabilities set 396 /* For init, we want to retain the capabilities set in the initial
404 * in the init_task struct. Thus we skip the usual 397 * task. Thus we skip the usual capability rules
405 * capability rules */ 398 */
406 if (!is_global_init(current)) { 399 if (!is_global_init(current)) {
407 new->cap_permitted = bprm->cap_post_exec_permitted; 400 if (effective)
408 if (bprm->cap_effective) 401 new->cap_effective = new->cap_permitted;
409 new->cap_effective = bprm->cap_post_exec_permitted;
410 else 402 else
411 cap_clear(new->cap_effective); 403 cap_clear(new->cap_effective);
412 } 404 }
405 bprm->cap_effective = effective;
413 406
414 /* 407 /*
415 * Audit candidate if current->cap_effective is set 408 * Audit candidate if current->cap_effective is set
@@ -425,23 +418,31 @@ int cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
425 */ 418 */
426 if (!cap_isclear(new->cap_effective)) { 419 if (!cap_isclear(new->cap_effective)) {
427 if (!cap_issubset(CAP_FULL_SET, new->cap_effective) || 420 if (!cap_issubset(CAP_FULL_SET, new->cap_effective) ||
428 bprm->e_uid != 0 || new->uid != 0 || 421 new->euid != 0 || new->uid != 0 ||
429 issecure(SECURE_NOROOT)) 422 issecure(SECURE_NOROOT)) {
430 audit_log_bprm_fcaps(bprm, new, old); 423 ret = audit_log_bprm_fcaps(bprm, new, old);
424 if (ret < 0)
425 return ret;
426 }
431 } 427 }
432 428
433 new->securebits &= ~issecure_mask(SECURE_KEEP_CAPS); 429 new->securebits &= ~issecure_mask(SECURE_KEEP_CAPS);
434 return commit_creds(new); 430 return 0;
435} 431}
436 432
437int cap_bprm_secureexec (struct linux_binprm *bprm) 433/*
434 * determine whether a secure execution is required
435 * - the creds have been committed at this point, and are no longer available
436 * through bprm
437 */
438int cap_bprm_secureexec(struct linux_binprm *bprm)
438{ 439{
439 const struct cred *cred = current_cred(); 440 const struct cred *cred = current_cred();
440 441
441 if (cred->uid != 0) { 442 if (cred->uid != 0) {
442 if (bprm->cap_effective) 443 if (bprm->cap_effective)
443 return 1; 444 return 1;
444 if (!cap_isclear(bprm->cap_post_exec_permitted)) 445 if (!cap_isclear(cred->cap_permitted))
445 return 1; 446 return 1;
446 } 447 }
447 448
@@ -477,7 +478,7 @@ int cap_inode_removexattr(struct dentry *dentry, const char *name)
477} 478}
478 479
479/* moved from kernel/sys.c. */ 480/* moved from kernel/sys.c. */
480/* 481/*
481 * cap_emulate_setxuid() fixes the effective / permitted capabilities of 482 * cap_emulate_setxuid() fixes the effective / permitted capabilities of
482 * a process after a call to setuid, setreuid, or setresuid. 483 * a process after a call to setuid, setreuid, or setresuid.
483 * 484 *
@@ -491,10 +492,10 @@ int cap_inode_removexattr(struct dentry *dentry, const char *name)
491 * 3) When set*uiding _from_ euid != 0 _to_ euid == 0, the effective 492 * 3) When set*uiding _from_ euid != 0 _to_ euid == 0, the effective
492 * capabilities are set to the permitted capabilities. 493 * capabilities are set to the permitted capabilities.
493 * 494 *
494 * fsuid is handled elsewhere. fsuid == 0 and {r,e,s}uid!= 0 should 495 * fsuid is handled elsewhere. fsuid == 0 and {r,e,s}uid!= 0 should
495 * never happen. 496 * never happen.
496 * 497 *
497 * -astor 498 * -astor
498 * 499 *
499 * cevans - New behaviour, Oct '99 500 * cevans - New behaviour, Oct '99
500 * A process may, via prctl(), elect to keep its capabilities when it 501 * A process may, via prctl(), elect to keep its capabilities when it
@@ -751,4 +752,3 @@ int cap_vm_enough_memory(struct mm_struct *mm, long pages)
751 cap_sys_admin = 1; 752 cap_sys_admin = 1;
752 return __vm_enough_memory(mm, pages, cap_sys_admin); 753 return __vm_enough_memory(mm, pages, cap_sys_admin);
753} 754}
754
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index df329f684a65..2f5d89e92b85 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -276,48 +276,6 @@ static int install_session_keyring(struct key *keyring)
276 276
277/*****************************************************************************/ 277/*****************************************************************************/
278/* 278/*
279 * deal with execve()
280 */
281int exec_keys(struct task_struct *tsk)
282{
283 struct thread_group_cred *tgcred = NULL;
284 struct cred *new;
285
286#ifdef CONFIG_KEYS
287 tgcred = kmalloc(sizeof(*tgcred), GFP_KERNEL);
288 if (!tgcred)
289 return -ENOMEM;
290#endif
291
292 new = prepare_creds();
293 if (new < 0)
294 return -ENOMEM;
295
296 /* newly exec'd tasks don't get a thread keyring */
297 key_put(new->thread_keyring);
298 new->thread_keyring = NULL;
299
300 /* create a new per-thread-group creds for all this set of threads to
301 * share */
302 memcpy(tgcred, new->tgcred, sizeof(struct thread_group_cred));
303
304 atomic_set(&tgcred->usage, 1);
305 spin_lock_init(&tgcred->lock);
306
307 /* inherit the session keyring; new process keyring */
308 key_get(tgcred->session_keyring);
309 tgcred->process_keyring = NULL;
310
311 release_tgcred(new);
312 new->tgcred = tgcred;
313
314 commit_creds(new);
315 return 0;
316
317} /* end exec_keys() */
318
319/*****************************************************************************/
320/*
321 * the filesystem user ID changed 279 * the filesystem user ID changed
322 */ 280 */
323void key_fsuid_changed(struct task_struct *tsk) 281void key_fsuid_changed(struct task_struct *tsk)
diff --git a/security/root_plug.c b/security/root_plug.c
index c3f68b5b372d..40fb4f15e27b 100644
--- a/security/root_plug.c
+++ b/security/root_plug.c
@@ -55,9 +55,9 @@ static int rootplug_bprm_check_security (struct linux_binprm *bprm)
55 struct usb_device *dev; 55 struct usb_device *dev;
56 56
57 root_dbg("file %s, e_uid = %d, e_gid = %d\n", 57 root_dbg("file %s, e_uid = %d, e_gid = %d\n",
58 bprm->filename, bprm->e_uid, bprm->e_gid); 58 bprm->filename, bprm->cred->euid, bprm->cred->egid);
59 59
60 if (bprm->e_gid == 0) { 60 if (bprm->cred->egid == 0) {
61 dev = usb_find_device(vendor_id, product_id); 61 dev = usb_find_device(vendor_id, product_id);
62 if (!dev) { 62 if (!dev) {
63 root_dbg("e_gid = 0, and device not found, " 63 root_dbg("e_gid = 0, and device not found, "
@@ -75,15 +75,12 @@ static struct security_operations rootplug_security_ops = {
75 .ptrace_may_access = cap_ptrace_may_access, 75 .ptrace_may_access = cap_ptrace_may_access,
76 .ptrace_traceme = cap_ptrace_traceme, 76 .ptrace_traceme = cap_ptrace_traceme,
77 .capget = cap_capget, 77 .capget = cap_capget,
78 .capset_check = cap_capset_check, 78 .capset = cap_capset,
79 .capset_set = cap_capset_set,
80 .capable = cap_capable, 79 .capable = cap_capable,
81 80
82 .bprm_apply_creds = cap_bprm_apply_creds, 81 .bprm_set_creds = cap_bprm_set_creds,
83 .bprm_set_security = cap_bprm_set_security,
84 82
85 .task_post_setuid = cap_task_post_setuid, 83 .task_fix_setuid = cap_task_fix_setuid,
86 .task_reparent_to_init = cap_task_reparent_to_init,
87 .task_prctl = cap_task_prctl, 84 .task_prctl = cap_task_prctl,
88 85
89 .bprm_check_security = rootplug_bprm_check_security, 86 .bprm_check_security = rootplug_bprm_check_security,
diff --git a/security/security.c b/security/security.c
index a55d739c6864..dc5babb2d6d8 100644
--- a/security/security.c
+++ b/security/security.c
@@ -213,34 +213,24 @@ int security_vm_enough_memory_kern(long pages)
213 return security_ops->vm_enough_memory(current->mm, pages); 213 return security_ops->vm_enough_memory(current->mm, pages);
214} 214}
215 215
216int security_bprm_alloc(struct linux_binprm *bprm) 216int security_bprm_set_creds(struct linux_binprm *bprm)
217{ 217{
218 return security_ops->bprm_alloc_security(bprm); 218 return security_ops->bprm_set_creds(bprm);
219} 219}
220 220
221void security_bprm_free(struct linux_binprm *bprm) 221int security_bprm_check(struct linux_binprm *bprm)
222{
223 security_ops->bprm_free_security(bprm);
224}
225
226int security_bprm_apply_creds(struct linux_binprm *bprm, int unsafe)
227{
228 return security_ops->bprm_apply_creds(bprm, unsafe);
229}
230
231void security_bprm_post_apply_creds(struct linux_binprm *bprm)
232{ 222{
233 security_ops->bprm_post_apply_creds(bprm); 223 return security_ops->bprm_check_security(bprm);
234} 224}
235 225
236int security_bprm_set(struct linux_binprm *bprm) 226void security_bprm_committing_creds(struct linux_binprm *bprm)
237{ 227{
238 return security_ops->bprm_set_security(bprm); 228 return security_ops->bprm_committing_creds(bprm);
239} 229}
240 230
241int security_bprm_check(struct linux_binprm *bprm) 231void security_bprm_committed_creds(struct linux_binprm *bprm)
242{ 232{
243 return security_ops->bprm_check_security(bprm); 233 return security_ops->bprm_committed_creds(bprm);
244} 234}
245 235
246int security_bprm_secureexec(struct linux_binprm *bprm) 236int security_bprm_secureexec(struct linux_binprm *bprm)
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index c71bba78872f..21a592184633 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2029,59 +2029,45 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
2029 2029
2030/* binprm security operations */ 2030/* binprm security operations */
2031 2031
2032static int selinux_bprm_alloc_security(struct linux_binprm *bprm) 2032static int selinux_bprm_set_creds(struct linux_binprm *bprm)
2033{ 2033{
2034 struct bprm_security_struct *bsec; 2034 const struct task_security_struct *old_tsec;
2035 2035 struct task_security_struct *new_tsec;
2036 bsec = kzalloc(sizeof(struct bprm_security_struct), GFP_KERNEL);
2037 if (!bsec)
2038 return -ENOMEM;
2039
2040 bsec->sid = SECINITSID_UNLABELED;
2041 bsec->set = 0;
2042
2043 bprm->security = bsec;
2044 return 0;
2045}
2046
2047static int selinux_bprm_set_security(struct linux_binprm *bprm)
2048{
2049 struct task_security_struct *tsec;
2050 struct inode *inode = bprm->file->f_path.dentry->d_inode;
2051 struct inode_security_struct *isec; 2036 struct inode_security_struct *isec;
2052 struct bprm_security_struct *bsec;
2053 u32 newsid;
2054 struct avc_audit_data ad; 2037 struct avc_audit_data ad;
2038 struct inode *inode = bprm->file->f_path.dentry->d_inode;
2055 int rc; 2039 int rc;
2056 2040
2057 rc = secondary_ops->bprm_set_security(bprm); 2041 rc = secondary_ops->bprm_set_creds(bprm);
2058 if (rc) 2042 if (rc)
2059 return rc; 2043 return rc;
2060 2044
2061 bsec = bprm->security; 2045 /* SELinux context only depends on initial program or script and not
2062 2046 * the script interpreter */
2063 if (bsec->set) 2047 if (bprm->cred_prepared)
2064 return 0; 2048 return 0;
2065 2049
2066 tsec = current_security(); 2050 old_tsec = current_security();
2051 new_tsec = bprm->cred->security;
2067 isec = inode->i_security; 2052 isec = inode->i_security;
2068 2053
2069 /* Default to the current task SID. */ 2054 /* Default to the current task SID. */
2070 bsec->sid = tsec->sid; 2055 new_tsec->sid = old_tsec->sid;
2056 new_tsec->osid = old_tsec->sid;
2071 2057
2072 /* Reset fs, key, and sock SIDs on execve. */ 2058 /* Reset fs, key, and sock SIDs on execve. */
2073 tsec->create_sid = 0; 2059 new_tsec->create_sid = 0;
2074 tsec->keycreate_sid = 0; 2060 new_tsec->keycreate_sid = 0;
2075 tsec->sockcreate_sid = 0; 2061 new_tsec->sockcreate_sid = 0;
2076 2062
2077 if (tsec->exec_sid) { 2063 if (old_tsec->exec_sid) {
2078 newsid = tsec->exec_sid; 2064 new_tsec->sid = old_tsec->exec_sid;
2079 /* Reset exec SID on execve. */ 2065 /* Reset exec SID on execve. */
2080 tsec->exec_sid = 0; 2066 new_tsec->exec_sid = 0;
2081 } else { 2067 } else {
2082 /* Check for a default transition on this program. */ 2068 /* Check for a default transition on this program. */
2083 rc = security_transition_sid(tsec->sid, isec->sid, 2069 rc = security_transition_sid(old_tsec->sid, isec->sid,
2084 SECCLASS_PROCESS, &newsid); 2070 SECCLASS_PROCESS, &new_tsec->sid);
2085 if (rc) 2071 if (rc)
2086 return rc; 2072 return rc;
2087 } 2073 }
@@ -2090,33 +2076,63 @@ static int selinux_bprm_set_security(struct linux_binprm *bprm)
2090 ad.u.fs.path = bprm->file->f_path; 2076 ad.u.fs.path = bprm->file->f_path;
2091 2077
2092 if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) 2078 if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)
2093 newsid = tsec->sid; 2079 new_tsec->sid = old_tsec->sid;
2094 2080
2095 if (tsec->sid == newsid) { 2081 if (new_tsec->sid == old_tsec->sid) {
2096 rc = avc_has_perm(tsec->sid, isec->sid, 2082 rc = avc_has_perm(old_tsec->sid, isec->sid,
2097 SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad); 2083 SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
2098 if (rc) 2084 if (rc)
2099 return rc; 2085 return rc;
2100 } else { 2086 } else {
2101 /* Check permissions for the transition. */ 2087 /* Check permissions for the transition. */
2102 rc = avc_has_perm(tsec->sid, newsid, 2088 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
2103 SECCLASS_PROCESS, PROCESS__TRANSITION, &ad); 2089 SECCLASS_PROCESS, PROCESS__TRANSITION, &ad);
2104 if (rc) 2090 if (rc)
2105 return rc; 2091 return rc;
2106 2092
2107 rc = avc_has_perm(newsid, isec->sid, 2093 rc = avc_has_perm(new_tsec->sid, isec->sid,
2108 SECCLASS_FILE, FILE__ENTRYPOINT, &ad); 2094 SECCLASS_FILE, FILE__ENTRYPOINT, &ad);
2109 if (rc) 2095 if (rc)
2110 return rc; 2096 return rc;
2111 2097
2112 /* Clear any possibly unsafe personality bits on exec: */ 2098 /* Check for shared state */
2113 current->personality &= ~PER_CLEAR_ON_SETID; 2099 if (bprm->unsafe & LSM_UNSAFE_SHARE) {
2100 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
2101 SECCLASS_PROCESS, PROCESS__SHARE,
2102 NULL);
2103 if (rc)
2104 return -EPERM;
2105 }
2106
2107 /* Make sure that anyone attempting to ptrace over a task that
2108 * changes its SID has the appropriate permit */
2109 if (bprm->unsafe &
2110 (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
2111 struct task_struct *tracer;
2112 struct task_security_struct *sec;
2113 u32 ptsid = 0;
2114
2115 rcu_read_lock();
2116 tracer = tracehook_tracer_task(current);
2117 if (likely(tracer != NULL)) {
2118 sec = __task_cred(tracer)->security;
2119 ptsid = sec->sid;
2120 }
2121 rcu_read_unlock();
2122
2123 if (ptsid != 0) {
2124 rc = avc_has_perm(ptsid, new_tsec->sid,
2125 SECCLASS_PROCESS,
2126 PROCESS__PTRACE, NULL);
2127 if (rc)
2128 return -EPERM;
2129 }
2130 }
2114 2131
2115 /* Set the security field to the new SID. */ 2132 /* Clear any possibly unsafe personality bits on exec: */
2116 bsec->sid = newsid; 2133 bprm->per_clear |= PER_CLEAR_ON_SETID;
2117 } 2134 }
2118 2135
2119 bsec->set = 1;
2120 return 0; 2136 return 0;
2121} 2137}
2122 2138
@@ -2125,7 +2141,6 @@ static int selinux_bprm_check_security(struct linux_binprm *bprm)
2125 return secondary_ops->bprm_check_security(bprm); 2141 return secondary_ops->bprm_check_security(bprm);
2126} 2142}
2127 2143
2128
2129static int selinux_bprm_secureexec(struct linux_binprm *bprm) 2144static int selinux_bprm_secureexec(struct linux_binprm *bprm)
2130{ 2145{
2131 const struct cred *cred = current_cred(); 2146 const struct cred *cred = current_cred();
@@ -2141,19 +2156,13 @@ static int selinux_bprm_secureexec(struct linux_binprm *bprm)
2141 the noatsecure permission is granted between 2156 the noatsecure permission is granted between
2142 the two SIDs, i.e. ahp returns 0. */ 2157 the two SIDs, i.e. ahp returns 0. */
2143 atsecure = avc_has_perm(osid, sid, 2158 atsecure = avc_has_perm(osid, sid,
2144 SECCLASS_PROCESS, 2159 SECCLASS_PROCESS,
2145 PROCESS__NOATSECURE, NULL); 2160 PROCESS__NOATSECURE, NULL);
2146 } 2161 }
2147 2162
2148 return (atsecure || secondary_ops->bprm_secureexec(bprm)); 2163 return (atsecure || secondary_ops->bprm_secureexec(bprm));
2149} 2164}
2150 2165
2151static void selinux_bprm_free_security(struct linux_binprm *bprm)
2152{
2153 kfree(bprm->security);
2154 bprm->security = NULL;
2155}
2156
2157extern struct vfsmount *selinuxfs_mount; 2166extern struct vfsmount *selinuxfs_mount;
2158extern struct dentry *selinux_null; 2167extern struct dentry *selinux_null;
2159 2168
@@ -2252,108 +2261,78 @@ static inline void flush_unauthorized_files(const struct cred *cred,
2252 spin_unlock(&files->file_lock); 2261 spin_unlock(&files->file_lock);
2253} 2262}
2254 2263
2255static int selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe) 2264/*
2265 * Prepare a process for imminent new credential changes due to exec
2266 */
2267static void selinux_bprm_committing_creds(struct linux_binprm *bprm)
2256{ 2268{
2257 struct task_security_struct *tsec; 2269 struct task_security_struct *new_tsec;
2258 struct bprm_security_struct *bsec; 2270 struct rlimit *rlim, *initrlim;
2259 struct cred *new; 2271 int rc, i;
2260 u32 sid;
2261 int rc;
2262
2263 rc = secondary_ops->bprm_apply_creds(bprm, unsafe);
2264 if (rc < 0)
2265 return rc;
2266
2267 new = prepare_creds();
2268 if (!new)
2269 return -ENOMEM;
2270 2272
2271 tsec = new->security; 2273 secondary_ops->bprm_committing_creds(bprm);
2272 2274
2273 bsec = bprm->security; 2275 new_tsec = bprm->cred->security;
2274 sid = bsec->sid; 2276 if (new_tsec->sid == new_tsec->osid)
2275 2277 return;
2276 tsec->osid = tsec->sid;
2277 bsec->unsafe = 0;
2278 if (tsec->sid != sid) {
2279 /* Check for shared state. If not ok, leave SID
2280 unchanged and kill. */
2281 if (unsafe & LSM_UNSAFE_SHARE) {
2282 rc = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
2283 PROCESS__SHARE, NULL);
2284 if (rc) {
2285 bsec->unsafe = 1;
2286 goto out;
2287 }
2288 }
2289 2278
2290 /* Check for ptracing, and update the task SID if ok. 2279 /* Close files for which the new task SID is not authorized. */
2291 Otherwise, leave SID unchanged and kill. */ 2280 flush_unauthorized_files(bprm->cred, current->files);
2292 if (unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
2293 struct task_struct *tracer;
2294 struct task_security_struct *sec;
2295 u32 ptsid = 0;
2296 2281
2297 rcu_read_lock(); 2282 /* Always clear parent death signal on SID transitions. */
2298 tracer = tracehook_tracer_task(current); 2283 current->pdeath_signal = 0;
2299 if (likely(tracer != NULL)) {
2300 sec = __task_cred(tracer)->security;
2301 ptsid = sec->sid;
2302 }
2303 rcu_read_unlock();
2304 2284
2305 if (ptsid != 0) { 2285 /* Check whether the new SID can inherit resource limits from the old
2306 rc = avc_has_perm(ptsid, sid, SECCLASS_PROCESS, 2286 * SID. If not, reset all soft limits to the lower of the current
2307 PROCESS__PTRACE, NULL); 2287 * task's hard limit and the init task's soft limit.
2308 if (rc) { 2288 *
2309 bsec->unsafe = 1; 2289 * Note that the setting of hard limits (even to lower them) can be
2310 goto out; 2290 * controlled by the setrlimit check. The inclusion of the init task's
2311 } 2291 * soft limit into the computation is to avoid resetting soft limits
2312 } 2292 * higher than the default soft limit for cases where the default is
2293 * lower than the hard limit, e.g. RLIMIT_CORE or RLIMIT_STACK.
2294 */
2295 rc = avc_has_perm(new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS,
2296 PROCESS__RLIMITINH, NULL);
2297 if (rc) {
2298 for (i = 0; i < RLIM_NLIMITS; i++) {
2299 rlim = current->signal->rlim + i;
2300 initrlim = init_task.signal->rlim + i;
2301 rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur);
2313 } 2302 }
2314 tsec->sid = sid; 2303 update_rlimit_cpu(rlim->rlim_cur);
2315 } 2304 }
2316
2317out:
2318 commit_creds(new);
2319 return 0;
2320} 2305}
2321 2306
2322/* 2307/*
2323 * called after apply_creds without the task lock held 2308 * Clean up the process immediately after the installation of new credentials
2309 * due to exec
2324 */ 2310 */
2325static void selinux_bprm_post_apply_creds(struct linux_binprm *bprm) 2311static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
2326{ 2312{
2327 const struct cred *cred = current_cred(); 2313 const struct task_security_struct *tsec = current_security();
2328 struct task_security_struct *tsec;
2329 struct rlimit *rlim, *initrlim;
2330 struct itimerval itimer; 2314 struct itimerval itimer;
2331 struct bprm_security_struct *bsec;
2332 struct sighand_struct *psig; 2315 struct sighand_struct *psig;
2316 u32 osid, sid;
2333 int rc, i; 2317 int rc, i;
2334 unsigned long flags; 2318 unsigned long flags;
2335 2319
2336 tsec = current_security(); 2320 secondary_ops->bprm_committed_creds(bprm);
2337 bsec = bprm->security;
2338 2321
2339 if (bsec->unsafe) { 2322 osid = tsec->osid;
2340 force_sig_specific(SIGKILL, current); 2323 sid = tsec->sid;
2341 return; 2324
2342 } 2325 if (sid == osid)
2343 if (tsec->osid == tsec->sid)
2344 return; 2326 return;
2345 2327
2346 /* Close files for which the new task SID is not authorized. */ 2328 /* Check whether the new SID can inherit signal state from the old SID.
2347 flush_unauthorized_files(cred, current->files); 2329 * If not, clear itimers to avoid subsequent signal generation and
2348 2330 * flush and unblock signals.
2349 /* Check whether the new SID can inherit signal state 2331 *
2350 from the old SID. If not, clear itimers to avoid 2332 * This must occur _after_ the task SID has been updated so that any
2351 subsequent signal generation and flush and unblock 2333 * kill done after the flush will be checked against the new SID.
2352 signals. This must occur _after_ the task SID has 2334 */
2353 been updated so that any kill done after the flush 2335 rc = avc_has_perm(osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL);
2354 will be checked against the new SID. */
2355 rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS,
2356 PROCESS__SIGINH, NULL);
2357 if (rc) { 2336 if (rc) {
2358 memset(&itimer, 0, sizeof itimer); 2337 memset(&itimer, 0, sizeof itimer);
2359 for (i = 0; i < 3; i++) 2338 for (i = 0; i < 3; i++)
@@ -2366,32 +2345,8 @@ static void selinux_bprm_post_apply_creds(struct linux_binprm *bprm)
2366 spin_unlock_irq(&current->sighand->siglock); 2345 spin_unlock_irq(&current->sighand->siglock);
2367 } 2346 }
2368 2347
2369 /* Always clear parent death signal on SID transitions. */ 2348 /* Wake up the parent if it is waiting so that it can recheck
2370 current->pdeath_signal = 0; 2349 * wait permission to the new task SID. */
2371
2372 /* Check whether the new SID can inherit resource limits
2373 from the old SID. If not, reset all soft limits to
2374 the lower of the current task's hard limit and the init
2375 task's soft limit. Note that the setting of hard limits
2376 (even to lower them) can be controlled by the setrlimit
2377 check. The inclusion of the init task's soft limit into
2378 the computation is to avoid resetting soft limits higher
2379 than the default soft limit for cases where the default
2380 is lower than the hard limit, e.g. RLIMIT_CORE or
2381 RLIMIT_STACK.*/
2382 rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS,
2383 PROCESS__RLIMITINH, NULL);
2384 if (rc) {
2385 for (i = 0; i < RLIM_NLIMITS; i++) {
2386 rlim = current->signal->rlim + i;
2387 initrlim = init_task.signal->rlim+i;
2388 rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur);
2389 }
2390 update_rlimit_cpu(rlim->rlim_cur);
2391 }
2392
2393 /* Wake up the parent if it is waiting so that it can
2394 recheck wait permission to the new task SID. */
2395 read_lock_irq(&tasklist_lock); 2350 read_lock_irq(&tasklist_lock);
2396 psig = current->parent->sighand; 2351 psig = current->parent->sighand;
2397 spin_lock_irqsave(&psig->siglock, flags); 2352 spin_lock_irqsave(&psig->siglock, flags);
@@ -5556,12 +5511,10 @@ static struct security_operations selinux_ops = {
5556 .netlink_send = selinux_netlink_send, 5511 .netlink_send = selinux_netlink_send,
5557 .netlink_recv = selinux_netlink_recv, 5512 .netlink_recv = selinux_netlink_recv,
5558 5513
5559 .bprm_alloc_security = selinux_bprm_alloc_security, 5514 .bprm_set_creds = selinux_bprm_set_creds,
5560 .bprm_free_security = selinux_bprm_free_security,
5561 .bprm_apply_creds = selinux_bprm_apply_creds,
5562 .bprm_post_apply_creds = selinux_bprm_post_apply_creds,
5563 .bprm_set_security = selinux_bprm_set_security,
5564 .bprm_check_security = selinux_bprm_check_security, 5515 .bprm_check_security = selinux_bprm_check_security,
5516 .bprm_committing_creds = selinux_bprm_committing_creds,
5517 .bprm_committed_creds = selinux_bprm_committed_creds,
5565 .bprm_secureexec = selinux_bprm_secureexec, 5518 .bprm_secureexec = selinux_bprm_secureexec,
5566 5519
5567 .sb_alloc_security = selinux_sb_alloc_security, 5520 .sb_alloc_security = selinux_sb_alloc_security,
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index f8be8d7fa26d..3cc45168f674 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -77,17 +77,6 @@ struct ipc_security_struct {
77 u32 sid; /* SID of IPC resource */ 77 u32 sid; /* SID of IPC resource */
78}; 78};
79 79
80struct bprm_security_struct {
81 u32 sid; /* SID for transformed process */
82 unsigned char set;
83
84 /*
85 * unsafe is used to share failure information from bprm_apply_creds()
86 * to bprm_post_apply_creds().
87 */
88 char unsafe;
89};
90
91struct netif_security_struct { 80struct netif_security_struct {
92 int ifindex; /* device index */ 81 int ifindex; /* device index */
93 u32 sid; /* SID for this interface */ 82 u32 sid; /* SID for this interface */
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index e952b397153d..de396742abf4 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -2596,8 +2596,7 @@ struct security_operations smack_ops = {
2596 .settime = cap_settime, 2596 .settime = cap_settime,
2597 .vm_enough_memory = cap_vm_enough_memory, 2597 .vm_enough_memory = cap_vm_enough_memory,
2598 2598
2599 .bprm_apply_creds = cap_bprm_apply_creds, 2599 .bprm_set_creds = cap_bprm_set_creds,
2600 .bprm_set_security = cap_bprm_set_security,
2601 .bprm_secureexec = cap_bprm_secureexec, 2600 .bprm_secureexec = cap_bprm_secureexec,
2602 2601
2603 .sb_alloc_security = smack_sb_alloc_security, 2602 .sb_alloc_security = smack_sb_alloc_security,