diff options
Diffstat (limited to 'security/apparmor')
-rw-r--r-- | security/apparmor/audit.c | 11 | ||||
-rw-r--r-- | security/apparmor/capability.c | 4 | ||||
-rw-r--r-- | security/apparmor/domain.c | 35 | ||||
-rw-r--r-- | security/apparmor/file.c | 2 | ||||
-rw-r--r-- | security/apparmor/include/audit.h | 1 | ||||
-rw-r--r-- | security/apparmor/ipc.c | 2 | ||||
-rw-r--r-- | security/apparmor/lib.c | 2 | ||||
-rw-r--r-- | security/apparmor/lsm.c | 6 | ||||
-rw-r--r-- | security/apparmor/path.c | 2 | ||||
-rw-r--r-- | security/apparmor/policy.c | 6 | ||||
-rw-r--r-- | security/apparmor/policy_unpack.c | 2 | ||||
-rw-r--r-- | security/apparmor/resource.c | 2 |
12 files changed, 62 insertions, 13 deletions
diff --git a/security/apparmor/audit.c b/security/apparmor/audit.c index cc3520d39a78..3ae28db5a64f 100644 --- a/security/apparmor/audit.c +++ b/security/apparmor/audit.c | |||
@@ -111,7 +111,7 @@ static const char *const aa_audit_type[] = { | |||
111 | static void audit_pre(struct audit_buffer *ab, void *ca) | 111 | static void audit_pre(struct audit_buffer *ab, void *ca) |
112 | { | 112 | { |
113 | struct common_audit_data *sa = ca; | 113 | struct common_audit_data *sa = ca; |
114 | struct task_struct *tsk = sa->tsk ? sa->tsk : current; | 114 | struct task_struct *tsk = sa->aad->tsk ? sa->aad->tsk : current; |
115 | 115 | ||
116 | if (aa_g_audit_header) { | 116 | if (aa_g_audit_header) { |
117 | audit_log_format(ab, "apparmor="); | 117 | audit_log_format(ab, "apparmor="); |
@@ -149,6 +149,12 @@ static void audit_pre(struct audit_buffer *ab, void *ca) | |||
149 | audit_log_format(ab, " name="); | 149 | audit_log_format(ab, " name="); |
150 | audit_log_untrustedstring(ab, sa->aad->name); | 150 | audit_log_untrustedstring(ab, sa->aad->name); |
151 | } | 151 | } |
152 | |||
153 | if (sa->aad->tsk) { | ||
154 | audit_log_format(ab, " pid=%d comm=", tsk->pid); | ||
155 | audit_log_untrustedstring(ab, tsk->comm); | ||
156 | } | ||
157 | |||
152 | } | 158 | } |
153 | 159 | ||
154 | /** | 160 | /** |
@@ -205,7 +211,8 @@ int aa_audit(int type, struct aa_profile *profile, gfp_t gfp, | |||
205 | aa_audit_msg(type, sa, cb); | 211 | aa_audit_msg(type, sa, cb); |
206 | 212 | ||
207 | if (sa->aad->type == AUDIT_APPARMOR_KILL) | 213 | if (sa->aad->type == AUDIT_APPARMOR_KILL) |
208 | (void)send_sig_info(SIGKILL, NULL, sa->tsk ? sa->tsk : current); | 214 | (void)send_sig_info(SIGKILL, NULL, |
215 | sa->aad->tsk ? sa->aad->tsk : current); | ||
209 | 216 | ||
210 | if (sa->aad->type == AUDIT_APPARMOR_ALLOWED) | 217 | if (sa->aad->type == AUDIT_APPARMOR_ALLOWED) |
211 | return complain_error(sa->aad->error); | 218 | return complain_error(sa->aad->error); |
diff --git a/security/apparmor/capability.c b/security/apparmor/capability.c index 088dba3bf7dc..887a5e948945 100644 --- a/security/apparmor/capability.c +++ b/security/apparmor/capability.c | |||
@@ -65,10 +65,10 @@ static int audit_caps(struct aa_profile *profile, struct task_struct *task, | |||
65 | int type = AUDIT_APPARMOR_AUTO; | 65 | int type = AUDIT_APPARMOR_AUTO; |
66 | struct common_audit_data sa; | 66 | struct common_audit_data sa; |
67 | struct apparmor_audit_data aad = {0,}; | 67 | struct apparmor_audit_data aad = {0,}; |
68 | COMMON_AUDIT_DATA_INIT(&sa, CAP); | 68 | sa.type = LSM_AUDIT_DATA_CAP; |
69 | sa.aad = &aad; | 69 | sa.aad = &aad; |
70 | sa.tsk = task; | ||
71 | sa.u.cap = cap; | 70 | sa.u.cap = cap; |
71 | sa.aad->tsk = task; | ||
72 | sa.aad->op = OP_CAPABLE; | 72 | sa.aad->op = OP_CAPABLE; |
73 | sa.aad->error = error; | 73 | sa.aad->error = error; |
74 | 74 | ||
diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c index 6327685c101e..b81ea10a17a3 100644 --- a/security/apparmor/domain.c +++ b/security/apparmor/domain.c | |||
@@ -394,6 +394,11 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm) | |||
394 | new_profile = find_attach(ns, &ns->base.profiles, name); | 394 | new_profile = find_attach(ns, &ns->base.profiles, name); |
395 | if (!new_profile) | 395 | if (!new_profile) |
396 | goto cleanup; | 396 | goto cleanup; |
397 | /* | ||
398 | * NOTE: Domain transitions from unconfined are allowed | ||
399 | * even when no_new_privs is set because this aways results | ||
400 | * in a further reduction of permissions. | ||
401 | */ | ||
397 | goto apply; | 402 | goto apply; |
398 | } | 403 | } |
399 | 404 | ||
@@ -455,6 +460,16 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm) | |||
455 | /* fail exec */ | 460 | /* fail exec */ |
456 | error = -EACCES; | 461 | error = -EACCES; |
457 | 462 | ||
463 | /* | ||
464 | * Policy has specified a domain transition, if no_new_privs then | ||
465 | * fail the exec. | ||
466 | */ | ||
467 | if (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS) { | ||
468 | aa_put_profile(new_profile); | ||
469 | error = -EPERM; | ||
470 | goto cleanup; | ||
471 | } | ||
472 | |||
458 | if (!new_profile) | 473 | if (!new_profile) |
459 | goto audit; | 474 | goto audit; |
460 | 475 | ||
@@ -609,6 +624,14 @@ int aa_change_hat(const char *hats[], int count, u64 token, bool permtest) | |||
609 | const char *target = NULL, *info = NULL; | 624 | const char *target = NULL, *info = NULL; |
610 | int error = 0; | 625 | int error = 0; |
611 | 626 | ||
627 | /* | ||
628 | * Fail explicitly requested domain transitions if no_new_privs. | ||
629 | * There is no exception for unconfined as change_hat is not | ||
630 | * available. | ||
631 | */ | ||
632 | if (current->no_new_privs) | ||
633 | return -EPERM; | ||
634 | |||
612 | /* released below */ | 635 | /* released below */ |
613 | cred = get_current_cred(); | 636 | cred = get_current_cred(); |
614 | cxt = cred->security; | 637 | cxt = cred->security; |
@@ -750,6 +773,18 @@ int aa_change_profile(const char *ns_name, const char *hname, bool onexec, | |||
750 | cxt = cred->security; | 773 | cxt = cred->security; |
751 | profile = aa_cred_profile(cred); | 774 | profile = aa_cred_profile(cred); |
752 | 775 | ||
776 | /* | ||
777 | * Fail explicitly requested domain transitions if no_new_privs | ||
778 | * and not unconfined. | ||
779 | * Domain transitions from unconfined are allowed even when | ||
780 | * no_new_privs is set because this aways results in a reduction | ||
781 | * of permissions. | ||
782 | */ | ||
783 | if (current->no_new_privs && !unconfined(profile)) { | ||
784 | put_cred(cred); | ||
785 | return -EPERM; | ||
786 | } | ||
787 | |||
753 | if (ns_name) { | 788 | if (ns_name) { |
754 | /* released below */ | 789 | /* released below */ |
755 | ns = aa_find_namespace(profile->ns, ns_name); | 790 | ns = aa_find_namespace(profile->ns, ns_name); |
diff --git a/security/apparmor/file.c b/security/apparmor/file.c index 2f8fcba9ce4b..cf19d4093ca4 100644 --- a/security/apparmor/file.c +++ b/security/apparmor/file.c | |||
@@ -108,7 +108,7 @@ int aa_audit_file(struct aa_profile *profile, struct file_perms *perms, | |||
108 | int type = AUDIT_APPARMOR_AUTO; | 108 | int type = AUDIT_APPARMOR_AUTO; |
109 | struct common_audit_data sa; | 109 | struct common_audit_data sa; |
110 | struct apparmor_audit_data aad = {0,}; | 110 | struct apparmor_audit_data aad = {0,}; |
111 | COMMON_AUDIT_DATA_INIT(&sa, NONE); | 111 | sa.type = LSM_AUDIT_DATA_NONE; |
112 | sa.aad = &aad; | 112 | sa.aad = &aad; |
113 | aad.op = op, | 113 | aad.op = op, |
114 | aad.fs.request = request; | 114 | aad.fs.request = request; |
diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h index 3868b1e5d5ba..4b7e18951aea 100644 --- a/security/apparmor/include/audit.h +++ b/security/apparmor/include/audit.h | |||
@@ -110,6 +110,7 @@ struct apparmor_audit_data { | |||
110 | void *profile; | 110 | void *profile; |
111 | const char *name; | 111 | const char *name; |
112 | const char *info; | 112 | const char *info; |
113 | struct task_struct *tsk; | ||
113 | union { | 114 | union { |
114 | void *target; | 115 | void *target; |
115 | struct { | 116 | struct { |
diff --git a/security/apparmor/ipc.c b/security/apparmor/ipc.c index c3da93a5150d..cf1071b14232 100644 --- a/security/apparmor/ipc.c +++ b/security/apparmor/ipc.c | |||
@@ -42,7 +42,7 @@ static int aa_audit_ptrace(struct aa_profile *profile, | |||
42 | { | 42 | { |
43 | struct common_audit_data sa; | 43 | struct common_audit_data sa; |
44 | struct apparmor_audit_data aad = {0,}; | 44 | struct apparmor_audit_data aad = {0,}; |
45 | COMMON_AUDIT_DATA_INIT(&sa, NONE); | 45 | sa.type = LSM_AUDIT_DATA_NONE; |
46 | sa.aad = &aad; | 46 | sa.aad = &aad; |
47 | aad.op = OP_PTRACE; | 47 | aad.op = OP_PTRACE; |
48 | aad.target = target; | 48 | aad.target = target; |
diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c index e75829ba0ff9..7430298116d6 100644 --- a/security/apparmor/lib.c +++ b/security/apparmor/lib.c | |||
@@ -66,7 +66,7 @@ void aa_info_message(const char *str) | |||
66 | if (audit_enabled) { | 66 | if (audit_enabled) { |
67 | struct common_audit_data sa; | 67 | struct common_audit_data sa; |
68 | struct apparmor_audit_data aad = {0,}; | 68 | struct apparmor_audit_data aad = {0,}; |
69 | COMMON_AUDIT_DATA_INIT(&sa, NONE); | 69 | sa.type = LSM_AUDIT_DATA_NONE; |
70 | sa.aad = &aad; | 70 | sa.aad = &aad; |
71 | aad.info = str; | 71 | aad.info = str; |
72 | aa_audit_msg(AUDIT_APPARMOR_STATUS, &sa, NULL); | 72 | aa_audit_msg(AUDIT_APPARMOR_STATUS, &sa, NULL); |
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index ad05d391974d..032daab449b0 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c | |||
@@ -373,7 +373,7 @@ static int apparmor_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) | |||
373 | AA_MAY_META_READ); | 373 | AA_MAY_META_READ); |
374 | } | 374 | } |
375 | 375 | ||
376 | static int apparmor_dentry_open(struct file *file, const struct cred *cred) | 376 | static int apparmor_file_open(struct file *file, const struct cred *cred) |
377 | { | 377 | { |
378 | struct aa_file_cxt *fcxt = file->f_security; | 378 | struct aa_file_cxt *fcxt = file->f_security; |
379 | struct aa_profile *profile; | 379 | struct aa_profile *profile; |
@@ -589,7 +589,7 @@ static int apparmor_setprocattr(struct task_struct *task, char *name, | |||
589 | } else { | 589 | } else { |
590 | struct common_audit_data sa; | 590 | struct common_audit_data sa; |
591 | struct apparmor_audit_data aad = {0,}; | 591 | struct apparmor_audit_data aad = {0,}; |
592 | COMMON_AUDIT_DATA_INIT(&sa, NONE); | 592 | sa.type = LSM_AUDIT_DATA_NONE; |
593 | sa.aad = &aad; | 593 | sa.aad = &aad; |
594 | aad.op = OP_SETPROCATTR; | 594 | aad.op = OP_SETPROCATTR; |
595 | aad.info = name; | 595 | aad.info = name; |
@@ -640,9 +640,9 @@ static struct security_operations apparmor_ops = { | |||
640 | .path_chmod = apparmor_path_chmod, | 640 | .path_chmod = apparmor_path_chmod, |
641 | .path_chown = apparmor_path_chown, | 641 | .path_chown = apparmor_path_chown, |
642 | .path_truncate = apparmor_path_truncate, | 642 | .path_truncate = apparmor_path_truncate, |
643 | .dentry_open = apparmor_dentry_open, | ||
644 | .inode_getattr = apparmor_inode_getattr, | 643 | .inode_getattr = apparmor_inode_getattr, |
645 | 644 | ||
645 | .file_open = apparmor_file_open, | ||
646 | .file_permission = apparmor_file_permission, | 646 | .file_permission = apparmor_file_permission, |
647 | .file_alloc_security = apparmor_file_alloc_security, | 647 | .file_alloc_security = apparmor_file_alloc_security, |
648 | .file_free_security = apparmor_file_free_security, | 648 | .file_free_security = apparmor_file_free_security, |
diff --git a/security/apparmor/path.c b/security/apparmor/path.c index 2daeea4f9266..e91ffee80162 100644 --- a/security/apparmor/path.c +++ b/security/apparmor/path.c | |||
@@ -94,6 +94,8 @@ static int d_namespace_path(struct path *path, char *buf, int buflen, | |||
94 | * be returned. | 94 | * be returned. |
95 | */ | 95 | */ |
96 | if (!res || IS_ERR(res)) { | 96 | if (!res || IS_ERR(res)) { |
97 | if (PTR_ERR(res) == -ENAMETOOLONG) | ||
98 | return -ENAMETOOLONG; | ||
97 | connected = 0; | 99 | connected = 0; |
98 | res = dentry_path_raw(path->dentry, buf, buflen); | 100 | res = dentry_path_raw(path->dentry, buf, buflen); |
99 | if (IS_ERR(res)) { | 101 | if (IS_ERR(res)) { |
diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c index f1f7506a464d..cf5fd220309b 100644 --- a/security/apparmor/policy.c +++ b/security/apparmor/policy.c | |||
@@ -903,6 +903,10 @@ struct aa_profile *aa_lookup_profile(struct aa_namespace *ns, const char *hname) | |||
903 | profile = aa_get_profile(__lookup_profile(&ns->base, hname)); | 903 | profile = aa_get_profile(__lookup_profile(&ns->base, hname)); |
904 | read_unlock(&ns->lock); | 904 | read_unlock(&ns->lock); |
905 | 905 | ||
906 | /* the unconfined profile is not in the regular profile list */ | ||
907 | if (!profile && strcmp(hname, "unconfined") == 0) | ||
908 | profile = aa_get_profile(ns->unconfined); | ||
909 | |||
906 | /* refcount released by caller */ | 910 | /* refcount released by caller */ |
907 | return profile; | 911 | return profile; |
908 | } | 912 | } |
@@ -965,7 +969,7 @@ static int audit_policy(int op, gfp_t gfp, const char *name, const char *info, | |||
965 | { | 969 | { |
966 | struct common_audit_data sa; | 970 | struct common_audit_data sa; |
967 | struct apparmor_audit_data aad = {0,}; | 971 | struct apparmor_audit_data aad = {0,}; |
968 | COMMON_AUDIT_DATA_INIT(&sa, NONE); | 972 | sa.type = LSM_AUDIT_DATA_NONE; |
969 | sa.aad = &aad; | 973 | sa.aad = &aad; |
970 | aad.op = op; | 974 | aad.op = op; |
971 | aad.name = name; | 975 | aad.name = name; |
diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c index deab7c7e8dc0..329b1fd30749 100644 --- a/security/apparmor/policy_unpack.c +++ b/security/apparmor/policy_unpack.c | |||
@@ -95,7 +95,7 @@ static int audit_iface(struct aa_profile *new, const char *name, | |||
95 | struct aa_profile *profile = __aa_current_profile(); | 95 | struct aa_profile *profile = __aa_current_profile(); |
96 | struct common_audit_data sa; | 96 | struct common_audit_data sa; |
97 | struct apparmor_audit_data aad = {0,}; | 97 | struct apparmor_audit_data aad = {0,}; |
98 | COMMON_AUDIT_DATA_INIT(&sa, NONE); | 98 | sa.type = LSM_AUDIT_DATA_NONE; |
99 | sa.aad = &aad; | 99 | sa.aad = &aad; |
100 | if (e) | 100 | if (e) |
101 | aad.iface.pos = e->pos - e->start; | 101 | aad.iface.pos = e->pos - e->start; |
diff --git a/security/apparmor/resource.c b/security/apparmor/resource.c index 2fe8613efe33..e1f3d7ef2c54 100644 --- a/security/apparmor/resource.c +++ b/security/apparmor/resource.c | |||
@@ -52,7 +52,7 @@ static int audit_resource(struct aa_profile *profile, unsigned int resource, | |||
52 | struct common_audit_data sa; | 52 | struct common_audit_data sa; |
53 | struct apparmor_audit_data aad = {0,}; | 53 | struct apparmor_audit_data aad = {0,}; |
54 | 54 | ||
55 | COMMON_AUDIT_DATA_INIT(&sa, NONE); | 55 | sa.type = LSM_AUDIT_DATA_NONE; |
56 | sa.aad = &aad; | 56 | sa.aad = &aad; |
57 | aad.op = OP_SETRLIMIT, | 57 | aad.op = OP_SETRLIMIT, |
58 | aad.rlim.rlim = resource; | 58 | aad.rlim.rlim = resource; |