diff options
33 files changed, 422 insertions, 350 deletions
@@ -681,7 +681,7 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, | |||
681 | 681 | ||
682 | f->f_op = fops_get(inode->i_fop); | 682 | f->f_op = fops_get(inode->i_fop); |
683 | 683 | ||
684 | error = security_dentry_open(f, cred); | 684 | error = security_file_open(f, cred); |
685 | if (error) | 685 | if (error) |
686 | goto cleanup_all; | 686 | goto cleanup_all; |
687 | 687 | ||
diff --git a/include/linux/lsm_audit.h b/include/linux/lsm_audit.h index fad48aab893b..1cc89e9df480 100644 --- a/include/linux/lsm_audit.h +++ b/include/linux/lsm_audit.h | |||
@@ -53,7 +53,6 @@ struct common_audit_data { | |||
53 | #define LSM_AUDIT_DATA_KMOD 8 | 53 | #define LSM_AUDIT_DATA_KMOD 8 |
54 | #define LSM_AUDIT_DATA_INODE 9 | 54 | #define LSM_AUDIT_DATA_INODE 9 |
55 | #define LSM_AUDIT_DATA_DENTRY 10 | 55 | #define LSM_AUDIT_DATA_DENTRY 10 |
56 | struct task_struct *tsk; | ||
57 | union { | 56 | union { |
58 | struct path path; | 57 | struct path path; |
59 | struct dentry *dentry; | 58 | struct dentry *dentry; |
@@ -93,11 +92,6 @@ int ipv4_skb_to_auditdata(struct sk_buff *skb, | |||
93 | int ipv6_skb_to_auditdata(struct sk_buff *skb, | 92 | int ipv6_skb_to_auditdata(struct sk_buff *skb, |
94 | struct common_audit_data *ad, u8 *proto); | 93 | struct common_audit_data *ad, u8 *proto); |
95 | 94 | ||
96 | /* Initialize an LSM audit data structure. */ | ||
97 | #define COMMON_AUDIT_DATA_INIT(_d, _t) \ | ||
98 | { memset((_d), 0, sizeof(struct common_audit_data)); \ | ||
99 | (_d)->type = LSM_AUDIT_DATA_##_t; } | ||
100 | |||
101 | void common_lsm_audit(struct common_audit_data *a, | 95 | void common_lsm_audit(struct common_audit_data *a, |
102 | void (*pre_audit)(struct audit_buffer *, void *), | 96 | void (*pre_audit)(struct audit_buffer *, void *), |
103 | void (*post_audit)(struct audit_buffer *, void *)); | 97 | void (*post_audit)(struct audit_buffer *, void *)); |
diff --git a/include/linux/security.h b/include/linux/security.h index 6e1dea93907a..ab0e091ce5fa 100644 --- a/include/linux/security.h +++ b/include/linux/security.h | |||
@@ -640,10 +640,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
640 | * to receive an open file descriptor via socket IPC. | 640 | * to receive an open file descriptor via socket IPC. |
641 | * @file contains the file structure being received. | 641 | * @file contains the file structure being received. |
642 | * Return 0 if permission is granted. | 642 | * Return 0 if permission is granted. |
643 | * | 643 | * @file_open |
644 | * Security hook for dentry | ||
645 | * | ||
646 | * @dentry_open | ||
647 | * Save open-time permission checking state for later use upon | 644 | * Save open-time permission checking state for later use upon |
648 | * file_permission, and recheck access if anything has changed | 645 | * file_permission, and recheck access if anything has changed |
649 | * since inode_permission. | 646 | * since inode_permission. |
@@ -1498,7 +1495,7 @@ struct security_operations { | |||
1498 | int (*file_send_sigiotask) (struct task_struct *tsk, | 1495 | int (*file_send_sigiotask) (struct task_struct *tsk, |
1499 | struct fown_struct *fown, int sig); | 1496 | struct fown_struct *fown, int sig); |
1500 | int (*file_receive) (struct file *file); | 1497 | int (*file_receive) (struct file *file); |
1501 | int (*dentry_open) (struct file *file, const struct cred *cred); | 1498 | int (*file_open) (struct file *file, const struct cred *cred); |
1502 | 1499 | ||
1503 | int (*task_create) (unsigned long clone_flags); | 1500 | int (*task_create) (unsigned long clone_flags); |
1504 | void (*task_free) (struct task_struct *task); | 1501 | void (*task_free) (struct task_struct *task); |
@@ -1757,7 +1754,7 @@ int security_file_set_fowner(struct file *file); | |||
1757 | int security_file_send_sigiotask(struct task_struct *tsk, | 1754 | int security_file_send_sigiotask(struct task_struct *tsk, |
1758 | struct fown_struct *fown, int sig); | 1755 | struct fown_struct *fown, int sig); |
1759 | int security_file_receive(struct file *file); | 1756 | int security_file_receive(struct file *file); |
1760 | int security_dentry_open(struct file *file, const struct cred *cred); | 1757 | int security_file_open(struct file *file, const struct cred *cred); |
1761 | int security_task_create(unsigned long clone_flags); | 1758 | int security_task_create(unsigned long clone_flags); |
1762 | void security_task_free(struct task_struct *task); | 1759 | void security_task_free(struct task_struct *task); |
1763 | int security_cred_alloc_blank(struct cred *cred, gfp_t gfp); | 1760 | int security_cred_alloc_blank(struct cred *cred, gfp_t gfp); |
@@ -2228,8 +2225,8 @@ static inline int security_file_receive(struct file *file) | |||
2228 | return 0; | 2225 | return 0; |
2229 | } | 2226 | } |
2230 | 2227 | ||
2231 | static inline int security_dentry_open(struct file *file, | 2228 | static inline int security_file_open(struct file *file, |
2232 | const struct cred *cred) | 2229 | const struct cred *cred) |
2233 | { | 2230 | { |
2234 | return 0; | 2231 | return 0; |
2235 | } | 2232 | } |
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 7661576b6f45..596f125658f6 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/cache.h> | 26 | #include <linux/cache.h> |
27 | #include <linux/audit.h> | 27 | #include <linux/audit.h> |
28 | #include <net/dst.h> | 28 | #include <net/dst.h> |
29 | #include <net/flow.h> | ||
29 | #include <net/xfrm.h> | 30 | #include <net/xfrm.h> |
30 | #include <net/ip.h> | 31 | #include <net/ip.h> |
31 | #ifdef CONFIG_XFRM_STATISTICS | 32 | #ifdef CONFIG_XFRM_STATISTICS |
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/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/policy.c b/security/apparmor/policy.c index 7f3f455d8eab..cf5fd220309b 100644 --- a/security/apparmor/policy.c +++ b/security/apparmor/policy.c | |||
@@ -969,7 +969,7 @@ static int audit_policy(int op, gfp_t gfp, const char *name, const char *info, | |||
969 | { | 969 | { |
970 | struct common_audit_data sa; | 970 | struct common_audit_data sa; |
971 | struct apparmor_audit_data aad = {0,}; | 971 | struct apparmor_audit_data aad = {0,}; |
972 | COMMON_AUDIT_DATA_INIT(&sa, NONE); | 972 | sa.type = LSM_AUDIT_DATA_NONE; |
973 | sa.aad = &aad; | 973 | sa.aad = &aad; |
974 | aad.op = op; | 974 | aad.op = op; |
975 | 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; |
diff --git a/security/capability.c b/security/capability.c index 5bb21b1c448c..fca889676c5e 100644 --- a/security/capability.c +++ b/security/capability.c | |||
@@ -348,7 +348,7 @@ static int cap_file_receive(struct file *file) | |||
348 | return 0; | 348 | return 0; |
349 | } | 349 | } |
350 | 350 | ||
351 | static int cap_dentry_open(struct file *file, const struct cred *cred) | 351 | static int cap_file_open(struct file *file, const struct cred *cred) |
352 | { | 352 | { |
353 | return 0; | 353 | return 0; |
354 | } | 354 | } |
@@ -956,7 +956,7 @@ void __init security_fixup_ops(struct security_operations *ops) | |||
956 | set_to_cap_if_null(ops, file_set_fowner); | 956 | set_to_cap_if_null(ops, file_set_fowner); |
957 | set_to_cap_if_null(ops, file_send_sigiotask); | 957 | set_to_cap_if_null(ops, file_send_sigiotask); |
958 | set_to_cap_if_null(ops, file_receive); | 958 | set_to_cap_if_null(ops, file_receive); |
959 | set_to_cap_if_null(ops, dentry_open); | 959 | set_to_cap_if_null(ops, file_open); |
960 | set_to_cap_if_null(ops, task_create); | 960 | set_to_cap_if_null(ops, task_create); |
961 | set_to_cap_if_null(ops, task_free); | 961 | set_to_cap_if_null(ops, task_free); |
962 | set_to_cap_if_null(ops, cred_alloc_blank); | 962 | set_to_cap_if_null(ops, cred_alloc_blank); |
diff --git a/security/lsm_audit.c b/security/lsm_audit.c index 90c129b0102f..8d8d97dbb389 100644 --- a/security/lsm_audit.c +++ b/security/lsm_audit.c | |||
@@ -213,12 +213,15 @@ static void dump_common_audit_data(struct audit_buffer *ab, | |||
213 | { | 213 | { |
214 | struct task_struct *tsk = current; | 214 | struct task_struct *tsk = current; |
215 | 215 | ||
216 | if (a->tsk) | 216 | /* |
217 | tsk = a->tsk; | 217 | * To keep stack sizes in check force programers to notice if they |
218 | if (tsk && tsk->pid) { | 218 | * start making this union too large! See struct lsm_network_audit |
219 | audit_log_format(ab, " pid=%d comm=", tsk->pid); | 219 | * as an example of how to deal with large data. |
220 | audit_log_untrustedstring(ab, tsk->comm); | 220 | */ |
221 | } | 221 | BUILD_BUG_ON(sizeof(a->u) > sizeof(void *)*2); |
222 | |||
223 | audit_log_format(ab, " pid=%d comm=", tsk->pid); | ||
224 | audit_log_untrustedstring(ab, tsk->comm); | ||
222 | 225 | ||
223 | switch (a->type) { | 226 | switch (a->type) { |
224 | case LSM_AUDIT_DATA_NONE: | 227 | case LSM_AUDIT_DATA_NONE: |
diff --git a/security/security.c b/security/security.c index bf619ffc9a4d..5497a57fba01 100644 --- a/security/security.c +++ b/security/security.c | |||
@@ -701,11 +701,11 @@ int security_file_receive(struct file *file) | |||
701 | return security_ops->file_receive(file); | 701 | return security_ops->file_receive(file); |
702 | } | 702 | } |
703 | 703 | ||
704 | int security_dentry_open(struct file *file, const struct cred *cred) | 704 | int security_file_open(struct file *file, const struct cred *cred) |
705 | { | 705 | { |
706 | int ret; | 706 | int ret; |
707 | 707 | ||
708 | ret = security_ops->dentry_open(file, cred); | 708 | ret = security_ops->file_open(file, cred); |
709 | if (ret) | 709 | if (ret) |
710 | return ret; | 710 | return ret; |
711 | 711 | ||
diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 8ee42b2a5f19..68d82daed257 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c | |||
@@ -65,14 +65,8 @@ struct avc_cache { | |||
65 | }; | 65 | }; |
66 | 66 | ||
67 | struct avc_callback_node { | 67 | struct avc_callback_node { |
68 | int (*callback) (u32 event, u32 ssid, u32 tsid, | 68 | int (*callback) (u32 event); |
69 | u16 tclass, u32 perms, | ||
70 | u32 *out_retained); | ||
71 | u32 events; | 69 | u32 events; |
72 | u32 ssid; | ||
73 | u32 tsid; | ||
74 | u16 tclass; | ||
75 | u32 perms; | ||
76 | struct avc_callback_node *next; | 70 | struct avc_callback_node *next; |
77 | }; | 71 | }; |
78 | 72 | ||
@@ -436,9 +430,9 @@ static void avc_audit_pre_callback(struct audit_buffer *ab, void *a) | |||
436 | { | 430 | { |
437 | struct common_audit_data *ad = a; | 431 | struct common_audit_data *ad = a; |
438 | audit_log_format(ab, "avc: %s ", | 432 | audit_log_format(ab, "avc: %s ", |
439 | ad->selinux_audit_data->slad->denied ? "denied" : "granted"); | 433 | ad->selinux_audit_data->denied ? "denied" : "granted"); |
440 | avc_dump_av(ab, ad->selinux_audit_data->slad->tclass, | 434 | avc_dump_av(ab, ad->selinux_audit_data->tclass, |
441 | ad->selinux_audit_data->slad->audited); | 435 | ad->selinux_audit_data->audited); |
442 | audit_log_format(ab, " for "); | 436 | audit_log_format(ab, " for "); |
443 | } | 437 | } |
444 | 438 | ||
@@ -452,25 +446,23 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a) | |||
452 | { | 446 | { |
453 | struct common_audit_data *ad = a; | 447 | struct common_audit_data *ad = a; |
454 | audit_log_format(ab, " "); | 448 | audit_log_format(ab, " "); |
455 | avc_dump_query(ab, ad->selinux_audit_data->slad->ssid, | 449 | avc_dump_query(ab, ad->selinux_audit_data->ssid, |
456 | ad->selinux_audit_data->slad->tsid, | 450 | ad->selinux_audit_data->tsid, |
457 | ad->selinux_audit_data->slad->tclass); | 451 | ad->selinux_audit_data->tclass); |
458 | } | 452 | } |
459 | 453 | ||
460 | /* This is the slow part of avc audit with big stack footprint */ | 454 | /* This is the slow part of avc audit with big stack footprint */ |
461 | static noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass, | 455 | noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass, |
462 | u32 requested, u32 audited, u32 denied, | 456 | u32 requested, u32 audited, u32 denied, |
463 | struct common_audit_data *a, | 457 | struct common_audit_data *a, |
464 | unsigned flags) | 458 | unsigned flags) |
465 | { | 459 | { |
466 | struct common_audit_data stack_data; | 460 | struct common_audit_data stack_data; |
467 | struct selinux_audit_data sad = {0,}; | 461 | struct selinux_audit_data sad; |
468 | struct selinux_late_audit_data slad; | ||
469 | 462 | ||
470 | if (!a) { | 463 | if (!a) { |
471 | a = &stack_data; | 464 | a = &stack_data; |
472 | COMMON_AUDIT_DATA_INIT(a, NONE); | 465 | a->type = LSM_AUDIT_DATA_NONE; |
473 | a->selinux_audit_data = &sad; | ||
474 | } | 466 | } |
475 | 467 | ||
476 | /* | 468 | /* |
@@ -484,104 +476,34 @@ static noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass, | |||
484 | (flags & MAY_NOT_BLOCK)) | 476 | (flags & MAY_NOT_BLOCK)) |
485 | return -ECHILD; | 477 | return -ECHILD; |
486 | 478 | ||
487 | slad.tclass = tclass; | 479 | sad.tclass = tclass; |
488 | slad.requested = requested; | 480 | sad.requested = requested; |
489 | slad.ssid = ssid; | 481 | sad.ssid = ssid; |
490 | slad.tsid = tsid; | 482 | sad.tsid = tsid; |
491 | slad.audited = audited; | 483 | sad.audited = audited; |
492 | slad.denied = denied; | 484 | sad.denied = denied; |
485 | |||
486 | a->selinux_audit_data = &sad; | ||
493 | 487 | ||
494 | a->selinux_audit_data->slad = &slad; | ||
495 | common_lsm_audit(a, avc_audit_pre_callback, avc_audit_post_callback); | 488 | common_lsm_audit(a, avc_audit_pre_callback, avc_audit_post_callback); |
496 | return 0; | 489 | return 0; |
497 | } | 490 | } |
498 | 491 | ||
499 | /** | 492 | /** |
500 | * avc_audit - Audit the granting or denial of permissions. | ||
501 | * @ssid: source security identifier | ||
502 | * @tsid: target security identifier | ||
503 | * @tclass: target security class | ||
504 | * @requested: requested permissions | ||
505 | * @avd: access vector decisions | ||
506 | * @result: result from avc_has_perm_noaudit | ||
507 | * @a: auxiliary audit data | ||
508 | * @flags: VFS walk flags | ||
509 | * | ||
510 | * Audit the granting or denial of permissions in accordance | ||
511 | * with the policy. This function is typically called by | ||
512 | * avc_has_perm() after a permission check, but can also be | ||
513 | * called directly by callers who use avc_has_perm_noaudit() | ||
514 | * in order to separate the permission check from the auditing. | ||
515 | * For example, this separation is useful when the permission check must | ||
516 | * be performed under a lock, to allow the lock to be released | ||
517 | * before calling the auditing code. | ||
518 | */ | ||
519 | inline int avc_audit(u32 ssid, u32 tsid, | ||
520 | u16 tclass, u32 requested, | ||
521 | struct av_decision *avd, int result, struct common_audit_data *a, | ||
522 | unsigned flags) | ||
523 | { | ||
524 | u32 denied, audited; | ||
525 | denied = requested & ~avd->allowed; | ||
526 | if (unlikely(denied)) { | ||
527 | audited = denied & avd->auditdeny; | ||
528 | /* | ||
529 | * a->selinux_audit_data->auditdeny is TRICKY! Setting a bit in | ||
530 | * this field means that ANY denials should NOT be audited if | ||
531 | * the policy contains an explicit dontaudit rule for that | ||
532 | * permission. Take notice that this is unrelated to the | ||
533 | * actual permissions that were denied. As an example lets | ||
534 | * assume: | ||
535 | * | ||
536 | * denied == READ | ||
537 | * avd.auditdeny & ACCESS == 0 (not set means explicit rule) | ||
538 | * selinux_audit_data->auditdeny & ACCESS == 1 | ||
539 | * | ||
540 | * We will NOT audit the denial even though the denied | ||
541 | * permission was READ and the auditdeny checks were for | ||
542 | * ACCESS | ||
543 | */ | ||
544 | if (a && | ||
545 | a->selinux_audit_data->auditdeny && | ||
546 | !(a->selinux_audit_data->auditdeny & avd->auditdeny)) | ||
547 | audited = 0; | ||
548 | } else if (result) | ||
549 | audited = denied = requested; | ||
550 | else | ||
551 | audited = requested & avd->auditallow; | ||
552 | if (likely(!audited)) | ||
553 | return 0; | ||
554 | |||
555 | return slow_avc_audit(ssid, tsid, tclass, | ||
556 | requested, audited, denied, | ||
557 | a, flags); | ||
558 | } | ||
559 | |||
560 | /** | ||
561 | * avc_add_callback - Register a callback for security events. | 493 | * avc_add_callback - Register a callback for security events. |
562 | * @callback: callback function | 494 | * @callback: callback function |
563 | * @events: security events | 495 | * @events: security events |
564 | * @ssid: source security identifier or %SECSID_WILD | ||
565 | * @tsid: target security identifier or %SECSID_WILD | ||
566 | * @tclass: target security class | ||
567 | * @perms: permissions | ||
568 | * | 496 | * |
569 | * Register a callback function for events in the set @events | 497 | * Register a callback function for events in the set @events. |
570 | * related to the SID pair (@ssid, @tsid) | 498 | * Returns %0 on success or -%ENOMEM if insufficient memory |
571 | * and the permissions @perms, interpreting | 499 | * exists to add the callback. |
572 | * @perms based on @tclass. Returns %0 on success or | ||
573 | * -%ENOMEM if insufficient memory exists to add the callback. | ||
574 | */ | 500 | */ |
575 | int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid, | 501 | int __init avc_add_callback(int (*callback)(u32 event), u32 events) |
576 | u16 tclass, u32 perms, | ||
577 | u32 *out_retained), | ||
578 | u32 events, u32 ssid, u32 tsid, | ||
579 | u16 tclass, u32 perms) | ||
580 | { | 502 | { |
581 | struct avc_callback_node *c; | 503 | struct avc_callback_node *c; |
582 | int rc = 0; | 504 | int rc = 0; |
583 | 505 | ||
584 | c = kmalloc(sizeof(*c), GFP_ATOMIC); | 506 | c = kmalloc(sizeof(*c), GFP_KERNEL); |
585 | if (!c) { | 507 | if (!c) { |
586 | rc = -ENOMEM; | 508 | rc = -ENOMEM; |
587 | goto out; | 509 | goto out; |
@@ -589,9 +511,6 @@ int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid, | |||
589 | 511 | ||
590 | c->callback = callback; | 512 | c->callback = callback; |
591 | c->events = events; | 513 | c->events = events; |
592 | c->ssid = ssid; | ||
593 | c->tsid = tsid; | ||
594 | c->perms = perms; | ||
595 | c->next = avc_callbacks; | 514 | c->next = avc_callbacks; |
596 | avc_callbacks = c; | 515 | avc_callbacks = c; |
597 | out: | 516 | out: |
@@ -731,8 +650,7 @@ int avc_ss_reset(u32 seqno) | |||
731 | 650 | ||
732 | for (c = avc_callbacks; c; c = c->next) { | 651 | for (c = avc_callbacks; c; c = c->next) { |
733 | if (c->events & AVC_CALLBACK_RESET) { | 652 | if (c->events & AVC_CALLBACK_RESET) { |
734 | tmprc = c->callback(AVC_CALLBACK_RESET, | 653 | tmprc = c->callback(AVC_CALLBACK_RESET); |
735 | 0, 0, 0, 0, NULL); | ||
736 | /* save the first error encountered for the return | 654 | /* save the first error encountered for the return |
737 | value and continue processing the callbacks */ | 655 | value and continue processing the callbacks */ |
738 | if (!rc) | 656 | if (!rc) |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 0b06685787b9..fa2341b68331 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -1420,16 +1420,13 @@ static int cred_has_capability(const struct cred *cred, | |||
1420 | int cap, int audit) | 1420 | int cap, int audit) |
1421 | { | 1421 | { |
1422 | struct common_audit_data ad; | 1422 | struct common_audit_data ad; |
1423 | struct selinux_audit_data sad = {0,}; | ||
1424 | struct av_decision avd; | 1423 | struct av_decision avd; |
1425 | u16 sclass; | 1424 | u16 sclass; |
1426 | u32 sid = cred_sid(cred); | 1425 | u32 sid = cred_sid(cred); |
1427 | u32 av = CAP_TO_MASK(cap); | 1426 | u32 av = CAP_TO_MASK(cap); |
1428 | int rc; | 1427 | int rc; |
1429 | 1428 | ||
1430 | COMMON_AUDIT_DATA_INIT(&ad, CAP); | 1429 | ad.type = LSM_AUDIT_DATA_CAP; |
1431 | ad.selinux_audit_data = &sad; | ||
1432 | ad.tsk = current; | ||
1433 | ad.u.cap = cap; | 1430 | ad.u.cap = cap; |
1434 | 1431 | ||
1435 | switch (CAP_TO_INDEX(cap)) { | 1432 | switch (CAP_TO_INDEX(cap)) { |
@@ -1488,20 +1485,6 @@ static int inode_has_perm(const struct cred *cred, | |||
1488 | return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags); | 1485 | return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags); |
1489 | } | 1486 | } |
1490 | 1487 | ||
1491 | static int inode_has_perm_noadp(const struct cred *cred, | ||
1492 | struct inode *inode, | ||
1493 | u32 perms, | ||
1494 | unsigned flags) | ||
1495 | { | ||
1496 | struct common_audit_data ad; | ||
1497 | struct selinux_audit_data sad = {0,}; | ||
1498 | |||
1499 | COMMON_AUDIT_DATA_INIT(&ad, INODE); | ||
1500 | ad.u.inode = inode; | ||
1501 | ad.selinux_audit_data = &sad; | ||
1502 | return inode_has_perm(cred, inode, perms, &ad, flags); | ||
1503 | } | ||
1504 | |||
1505 | /* Same as inode_has_perm, but pass explicit audit data containing | 1488 | /* Same as inode_has_perm, but pass explicit audit data containing |
1506 | the dentry to help the auditing code to more easily generate the | 1489 | the dentry to help the auditing code to more easily generate the |
1507 | pathname if needed. */ | 1490 | pathname if needed. */ |
@@ -1511,11 +1494,9 @@ static inline int dentry_has_perm(const struct cred *cred, | |||
1511 | { | 1494 | { |
1512 | struct inode *inode = dentry->d_inode; | 1495 | struct inode *inode = dentry->d_inode; |
1513 | struct common_audit_data ad; | 1496 | struct common_audit_data ad; |
1514 | struct selinux_audit_data sad = {0,}; | ||
1515 | 1497 | ||
1516 | COMMON_AUDIT_DATA_INIT(&ad, DENTRY); | 1498 | ad.type = LSM_AUDIT_DATA_DENTRY; |
1517 | ad.u.dentry = dentry; | 1499 | ad.u.dentry = dentry; |
1518 | ad.selinux_audit_data = &sad; | ||
1519 | return inode_has_perm(cred, inode, av, &ad, 0); | 1500 | return inode_has_perm(cred, inode, av, &ad, 0); |
1520 | } | 1501 | } |
1521 | 1502 | ||
@@ -1528,11 +1509,9 @@ static inline int path_has_perm(const struct cred *cred, | |||
1528 | { | 1509 | { |
1529 | struct inode *inode = path->dentry->d_inode; | 1510 | struct inode *inode = path->dentry->d_inode; |
1530 | struct common_audit_data ad; | 1511 | struct common_audit_data ad; |
1531 | struct selinux_audit_data sad = {0,}; | ||
1532 | 1512 | ||
1533 | COMMON_AUDIT_DATA_INIT(&ad, PATH); | 1513 | ad.type = LSM_AUDIT_DATA_PATH; |
1534 | ad.u.path = *path; | 1514 | ad.u.path = *path; |
1535 | ad.selinux_audit_data = &sad; | ||
1536 | return inode_has_perm(cred, inode, av, &ad, 0); | 1515 | return inode_has_perm(cred, inode, av, &ad, 0); |
1537 | } | 1516 | } |
1538 | 1517 | ||
@@ -1551,13 +1530,11 @@ static int file_has_perm(const struct cred *cred, | |||
1551 | struct file_security_struct *fsec = file->f_security; | 1530 | struct file_security_struct *fsec = file->f_security; |
1552 | struct inode *inode = file->f_path.dentry->d_inode; | 1531 | struct inode *inode = file->f_path.dentry->d_inode; |
1553 | struct common_audit_data ad; | 1532 | struct common_audit_data ad; |
1554 | struct selinux_audit_data sad = {0,}; | ||
1555 | u32 sid = cred_sid(cred); | 1533 | u32 sid = cred_sid(cred); |
1556 | int rc; | 1534 | int rc; |
1557 | 1535 | ||
1558 | COMMON_AUDIT_DATA_INIT(&ad, PATH); | 1536 | ad.type = LSM_AUDIT_DATA_PATH; |
1559 | ad.u.path = file->f_path; | 1537 | ad.u.path = file->f_path; |
1560 | ad.selinux_audit_data = &sad; | ||
1561 | 1538 | ||
1562 | if (sid != fsec->sid) { | 1539 | if (sid != fsec->sid) { |
1563 | rc = avc_has_perm(sid, fsec->sid, | 1540 | rc = avc_has_perm(sid, fsec->sid, |
@@ -1587,7 +1564,6 @@ static int may_create(struct inode *dir, | |||
1587 | struct superblock_security_struct *sbsec; | 1564 | struct superblock_security_struct *sbsec; |
1588 | u32 sid, newsid; | 1565 | u32 sid, newsid; |
1589 | struct common_audit_data ad; | 1566 | struct common_audit_data ad; |
1590 | struct selinux_audit_data sad = {0,}; | ||
1591 | int rc; | 1567 | int rc; |
1592 | 1568 | ||
1593 | dsec = dir->i_security; | 1569 | dsec = dir->i_security; |
@@ -1596,9 +1572,8 @@ static int may_create(struct inode *dir, | |||
1596 | sid = tsec->sid; | 1572 | sid = tsec->sid; |
1597 | newsid = tsec->create_sid; | 1573 | newsid = tsec->create_sid; |
1598 | 1574 | ||
1599 | COMMON_AUDIT_DATA_INIT(&ad, DENTRY); | 1575 | ad.type = LSM_AUDIT_DATA_DENTRY; |
1600 | ad.u.dentry = dentry; | 1576 | ad.u.dentry = dentry; |
1601 | ad.selinux_audit_data = &sad; | ||
1602 | 1577 | ||
1603 | rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, | 1578 | rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, |
1604 | DIR__ADD_NAME | DIR__SEARCH, | 1579 | DIR__ADD_NAME | DIR__SEARCH, |
@@ -1643,7 +1618,6 @@ static int may_link(struct inode *dir, | |||
1643 | { | 1618 | { |
1644 | struct inode_security_struct *dsec, *isec; | 1619 | struct inode_security_struct *dsec, *isec; |
1645 | struct common_audit_data ad; | 1620 | struct common_audit_data ad; |
1646 | struct selinux_audit_data sad = {0,}; | ||
1647 | u32 sid = current_sid(); | 1621 | u32 sid = current_sid(); |
1648 | u32 av; | 1622 | u32 av; |
1649 | int rc; | 1623 | int rc; |
@@ -1651,9 +1625,8 @@ static int may_link(struct inode *dir, | |||
1651 | dsec = dir->i_security; | 1625 | dsec = dir->i_security; |
1652 | isec = dentry->d_inode->i_security; | 1626 | isec = dentry->d_inode->i_security; |
1653 | 1627 | ||
1654 | COMMON_AUDIT_DATA_INIT(&ad, DENTRY); | 1628 | ad.type = LSM_AUDIT_DATA_DENTRY; |
1655 | ad.u.dentry = dentry; | 1629 | ad.u.dentry = dentry; |
1656 | ad.selinux_audit_data = &sad; | ||
1657 | 1630 | ||
1658 | av = DIR__SEARCH; | 1631 | av = DIR__SEARCH; |
1659 | av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME); | 1632 | av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME); |
@@ -1688,7 +1661,6 @@ static inline int may_rename(struct inode *old_dir, | |||
1688 | { | 1661 | { |
1689 | struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec; | 1662 | struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec; |
1690 | struct common_audit_data ad; | 1663 | struct common_audit_data ad; |
1691 | struct selinux_audit_data sad = {0,}; | ||
1692 | u32 sid = current_sid(); | 1664 | u32 sid = current_sid(); |
1693 | u32 av; | 1665 | u32 av; |
1694 | int old_is_dir, new_is_dir; | 1666 | int old_is_dir, new_is_dir; |
@@ -1699,8 +1671,7 @@ static inline int may_rename(struct inode *old_dir, | |||
1699 | old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode); | 1671 | old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode); |
1700 | new_dsec = new_dir->i_security; | 1672 | new_dsec = new_dir->i_security; |
1701 | 1673 | ||
1702 | COMMON_AUDIT_DATA_INIT(&ad, DENTRY); | 1674 | ad.type = LSM_AUDIT_DATA_DENTRY; |
1703 | ad.selinux_audit_data = &sad; | ||
1704 | 1675 | ||
1705 | ad.u.dentry = old_dentry; | 1676 | ad.u.dentry = old_dentry; |
1706 | rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR, | 1677 | rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR, |
@@ -1986,7 +1957,6 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) | |||
1986 | struct task_security_struct *new_tsec; | 1957 | struct task_security_struct *new_tsec; |
1987 | struct inode_security_struct *isec; | 1958 | struct inode_security_struct *isec; |
1988 | struct common_audit_data ad; | 1959 | struct common_audit_data ad; |
1989 | struct selinux_audit_data sad = {0,}; | ||
1990 | struct inode *inode = bprm->file->f_path.dentry->d_inode; | 1960 | struct inode *inode = bprm->file->f_path.dentry->d_inode; |
1991 | int rc; | 1961 | int rc; |
1992 | 1962 | ||
@@ -2032,8 +2002,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) | |||
2032 | return rc; | 2002 | return rc; |
2033 | } | 2003 | } |
2034 | 2004 | ||
2035 | COMMON_AUDIT_DATA_INIT(&ad, PATH); | 2005 | ad.type = LSM_AUDIT_DATA_PATH; |
2036 | ad.selinux_audit_data = &sad; | ||
2037 | ad.u.path = bprm->file->f_path; | 2006 | ad.u.path = bprm->file->f_path; |
2038 | 2007 | ||
2039 | if ((bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) || | 2008 | if ((bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) || |
@@ -2123,8 +2092,6 @@ static int selinux_bprm_secureexec(struct linux_binprm *bprm) | |||
2123 | static inline void flush_unauthorized_files(const struct cred *cred, | 2092 | static inline void flush_unauthorized_files(const struct cred *cred, |
2124 | struct files_struct *files) | 2093 | struct files_struct *files) |
2125 | { | 2094 | { |
2126 | struct common_audit_data ad; | ||
2127 | struct selinux_audit_data sad = {0,}; | ||
2128 | struct file *file, *devnull = NULL; | 2095 | struct file *file, *devnull = NULL; |
2129 | struct tty_struct *tty; | 2096 | struct tty_struct *tty; |
2130 | struct fdtable *fdt; | 2097 | struct fdtable *fdt; |
@@ -2136,21 +2103,17 @@ static inline void flush_unauthorized_files(const struct cred *cred, | |||
2136 | spin_lock(&tty_files_lock); | 2103 | spin_lock(&tty_files_lock); |
2137 | if (!list_empty(&tty->tty_files)) { | 2104 | if (!list_empty(&tty->tty_files)) { |
2138 | struct tty_file_private *file_priv; | 2105 | struct tty_file_private *file_priv; |
2139 | struct inode *inode; | ||
2140 | 2106 | ||
2141 | /* Revalidate access to controlling tty. | 2107 | /* Revalidate access to controlling tty. |
2142 | Use inode_has_perm on the tty inode directly rather | 2108 | Use path_has_perm on the tty path directly rather |
2143 | than using file_has_perm, as this particular open | 2109 | than using file_has_perm, as this particular open |
2144 | file may belong to another process and we are only | 2110 | file may belong to another process and we are only |
2145 | interested in the inode-based check here. */ | 2111 | interested in the inode-based check here. */ |
2146 | file_priv = list_first_entry(&tty->tty_files, | 2112 | file_priv = list_first_entry(&tty->tty_files, |
2147 | struct tty_file_private, list); | 2113 | struct tty_file_private, list); |
2148 | file = file_priv->file; | 2114 | file = file_priv->file; |
2149 | inode = file->f_path.dentry->d_inode; | 2115 | if (path_has_perm(cred, &file->f_path, FILE__READ | FILE__WRITE)) |
2150 | if (inode_has_perm_noadp(cred, inode, | ||
2151 | FILE__READ | FILE__WRITE, 0)) { | ||
2152 | drop_tty = 1; | 2116 | drop_tty = 1; |
2153 | } | ||
2154 | } | 2117 | } |
2155 | spin_unlock(&tty_files_lock); | 2118 | spin_unlock(&tty_files_lock); |
2156 | tty_kref_put(tty); | 2119 | tty_kref_put(tty); |
@@ -2160,10 +2123,6 @@ static inline void flush_unauthorized_files(const struct cred *cred, | |||
2160 | no_tty(); | 2123 | no_tty(); |
2161 | 2124 | ||
2162 | /* Revalidate access to inherited open files. */ | 2125 | /* Revalidate access to inherited open files. */ |
2163 | |||
2164 | COMMON_AUDIT_DATA_INIT(&ad, INODE); | ||
2165 | ad.selinux_audit_data = &sad; | ||
2166 | |||
2167 | spin_lock(&files->file_lock); | 2126 | spin_lock(&files->file_lock); |
2168 | for (;;) { | 2127 | for (;;) { |
2169 | unsigned long set, i; | 2128 | unsigned long set, i; |
@@ -2500,7 +2459,6 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) | |||
2500 | { | 2459 | { |
2501 | const struct cred *cred = current_cred(); | 2460 | const struct cred *cred = current_cred(); |
2502 | struct common_audit_data ad; | 2461 | struct common_audit_data ad; |
2503 | struct selinux_audit_data sad = {0,}; | ||
2504 | int rc; | 2462 | int rc; |
2505 | 2463 | ||
2506 | rc = superblock_doinit(sb, data); | 2464 | rc = superblock_doinit(sb, data); |
@@ -2511,8 +2469,7 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) | |||
2511 | if (flags & MS_KERNMOUNT) | 2469 | if (flags & MS_KERNMOUNT) |
2512 | return 0; | 2470 | return 0; |
2513 | 2471 | ||
2514 | COMMON_AUDIT_DATA_INIT(&ad, DENTRY); | 2472 | ad.type = LSM_AUDIT_DATA_DENTRY; |
2515 | ad.selinux_audit_data = &sad; | ||
2516 | ad.u.dentry = sb->s_root; | 2473 | ad.u.dentry = sb->s_root; |
2517 | return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad); | 2474 | return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad); |
2518 | } | 2475 | } |
@@ -2521,10 +2478,8 @@ static int selinux_sb_statfs(struct dentry *dentry) | |||
2521 | { | 2478 | { |
2522 | const struct cred *cred = current_cred(); | 2479 | const struct cred *cred = current_cred(); |
2523 | struct common_audit_data ad; | 2480 | struct common_audit_data ad; |
2524 | struct selinux_audit_data sad = {0,}; | ||
2525 | 2481 | ||
2526 | COMMON_AUDIT_DATA_INIT(&ad, DENTRY); | 2482 | ad.type = LSM_AUDIT_DATA_DENTRY; |
2527 | ad.selinux_audit_data = &sad; | ||
2528 | ad.u.dentry = dentry->d_sb->s_root; | 2483 | ad.u.dentry = dentry->d_sb->s_root; |
2529 | return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad); | 2484 | return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad); |
2530 | } | 2485 | } |
@@ -2684,14 +2639,35 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *na | |||
2684 | return dentry_has_perm(cred, dentry, FILE__READ); | 2639 | return dentry_has_perm(cred, dentry, FILE__READ); |
2685 | } | 2640 | } |
2686 | 2641 | ||
2642 | static noinline int audit_inode_permission(struct inode *inode, | ||
2643 | u32 perms, u32 audited, u32 denied, | ||
2644 | unsigned flags) | ||
2645 | { | ||
2646 | struct common_audit_data ad; | ||
2647 | struct inode_security_struct *isec = inode->i_security; | ||
2648 | int rc; | ||
2649 | |||
2650 | ad.type = LSM_AUDIT_DATA_INODE; | ||
2651 | ad.u.inode = inode; | ||
2652 | |||
2653 | rc = slow_avc_audit(current_sid(), isec->sid, isec->sclass, perms, | ||
2654 | audited, denied, &ad, flags); | ||
2655 | if (rc) | ||
2656 | return rc; | ||
2657 | return 0; | ||
2658 | } | ||
2659 | |||
2687 | static int selinux_inode_permission(struct inode *inode, int mask) | 2660 | static int selinux_inode_permission(struct inode *inode, int mask) |
2688 | { | 2661 | { |
2689 | const struct cred *cred = current_cred(); | 2662 | const struct cred *cred = current_cred(); |
2690 | struct common_audit_data ad; | ||
2691 | struct selinux_audit_data sad = {0,}; | ||
2692 | u32 perms; | 2663 | u32 perms; |
2693 | bool from_access; | 2664 | bool from_access; |
2694 | unsigned flags = mask & MAY_NOT_BLOCK; | 2665 | unsigned flags = mask & MAY_NOT_BLOCK; |
2666 | struct inode_security_struct *isec; | ||
2667 | u32 sid; | ||
2668 | struct av_decision avd; | ||
2669 | int rc, rc2; | ||
2670 | u32 audited, denied; | ||
2695 | 2671 | ||
2696 | from_access = mask & MAY_ACCESS; | 2672 | from_access = mask & MAY_ACCESS; |
2697 | mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND); | 2673 | mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND); |
@@ -2700,22 +2676,34 @@ static int selinux_inode_permission(struct inode *inode, int mask) | |||
2700 | if (!mask) | 2676 | if (!mask) |
2701 | return 0; | 2677 | return 0; |
2702 | 2678 | ||
2703 | COMMON_AUDIT_DATA_INIT(&ad, INODE); | 2679 | validate_creds(cred); |
2704 | ad.selinux_audit_data = &sad; | ||
2705 | ad.u.inode = inode; | ||
2706 | 2680 | ||
2707 | if (from_access) | 2681 | if (unlikely(IS_PRIVATE(inode))) |
2708 | ad.selinux_audit_data->auditdeny |= FILE__AUDIT_ACCESS; | 2682 | return 0; |
2709 | 2683 | ||
2710 | perms = file_mask_to_av(inode->i_mode, mask); | 2684 | perms = file_mask_to_av(inode->i_mode, mask); |
2711 | 2685 | ||
2712 | return inode_has_perm(cred, inode, perms, &ad, flags); | 2686 | sid = cred_sid(cred); |
2687 | isec = inode->i_security; | ||
2688 | |||
2689 | rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass, perms, 0, &avd); | ||
2690 | audited = avc_audit_required(perms, &avd, rc, | ||
2691 | from_access ? FILE__AUDIT_ACCESS : 0, | ||
2692 | &denied); | ||
2693 | if (likely(!audited)) | ||
2694 | return rc; | ||
2695 | |||
2696 | rc2 = audit_inode_permission(inode, perms, audited, denied, flags); | ||
2697 | if (rc2) | ||
2698 | return rc2; | ||
2699 | return rc; | ||
2713 | } | 2700 | } |
2714 | 2701 | ||
2715 | static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) | 2702 | static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) |
2716 | { | 2703 | { |
2717 | const struct cred *cred = current_cred(); | 2704 | const struct cred *cred = current_cred(); |
2718 | unsigned int ia_valid = iattr->ia_valid; | 2705 | unsigned int ia_valid = iattr->ia_valid; |
2706 | __u32 av = FILE__WRITE; | ||
2719 | 2707 | ||
2720 | /* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */ | 2708 | /* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */ |
2721 | if (ia_valid & ATTR_FORCE) { | 2709 | if (ia_valid & ATTR_FORCE) { |
@@ -2729,7 +2717,10 @@ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) | |||
2729 | ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET)) | 2717 | ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET)) |
2730 | return dentry_has_perm(cred, dentry, FILE__SETATTR); | 2718 | return dentry_has_perm(cred, dentry, FILE__SETATTR); |
2731 | 2719 | ||
2732 | return dentry_has_perm(cred, dentry, FILE__WRITE); | 2720 | if (ia_valid & ATTR_SIZE) |
2721 | av |= FILE__OPEN; | ||
2722 | |||
2723 | return dentry_has_perm(cred, dentry, av); | ||
2733 | } | 2724 | } |
2734 | 2725 | ||
2735 | static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) | 2726 | static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) |
@@ -2771,7 +2762,6 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, | |||
2771 | struct inode_security_struct *isec = inode->i_security; | 2762 | struct inode_security_struct *isec = inode->i_security; |
2772 | struct superblock_security_struct *sbsec; | 2763 | struct superblock_security_struct *sbsec; |
2773 | struct common_audit_data ad; | 2764 | struct common_audit_data ad; |
2774 | struct selinux_audit_data sad = {0,}; | ||
2775 | u32 newsid, sid = current_sid(); | 2765 | u32 newsid, sid = current_sid(); |
2776 | int rc = 0; | 2766 | int rc = 0; |
2777 | 2767 | ||
@@ -2785,8 +2775,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, | |||
2785 | if (!inode_owner_or_capable(inode)) | 2775 | if (!inode_owner_or_capable(inode)) |
2786 | return -EPERM; | 2776 | return -EPERM; |
2787 | 2777 | ||
2788 | COMMON_AUDIT_DATA_INIT(&ad, DENTRY); | 2778 | ad.type = LSM_AUDIT_DATA_DENTRY; |
2789 | ad.selinux_audit_data = &sad; | ||
2790 | ad.u.dentry = dentry; | 2779 | ad.u.dentry = dentry; |
2791 | 2780 | ||
2792 | rc = avc_has_perm(sid, isec->sid, isec->sclass, | 2781 | rc = avc_has_perm(sid, isec->sid, isec->sclass, |
@@ -2796,8 +2785,25 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, | |||
2796 | 2785 | ||
2797 | rc = security_context_to_sid(value, size, &newsid); | 2786 | rc = security_context_to_sid(value, size, &newsid); |
2798 | if (rc == -EINVAL) { | 2787 | if (rc == -EINVAL) { |
2799 | if (!capable(CAP_MAC_ADMIN)) | 2788 | if (!capable(CAP_MAC_ADMIN)) { |
2789 | struct audit_buffer *ab; | ||
2790 | size_t audit_size; | ||
2791 | const char *str; | ||
2792 | |||
2793 | /* We strip a nul only if it is at the end, otherwise the | ||
2794 | * context contains a nul and we should audit that */ | ||
2795 | str = value; | ||
2796 | if (str[size - 1] == '\0') | ||
2797 | audit_size = size - 1; | ||
2798 | else | ||
2799 | audit_size = size; | ||
2800 | ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR); | ||
2801 | audit_log_format(ab, "op=setxattr invalid_context="); | ||
2802 | audit_log_n_untrustedstring(ab, value, audit_size); | ||
2803 | audit_log_end(ab); | ||
2804 | |||
2800 | return rc; | 2805 | return rc; |
2806 | } | ||
2801 | rc = security_context_to_sid_force(value, size, &newsid); | 2807 | rc = security_context_to_sid_force(value, size, &newsid); |
2802 | } | 2808 | } |
2803 | if (rc) | 2809 | if (rc) |
@@ -2977,7 +2983,7 @@ static int selinux_file_permission(struct file *file, int mask) | |||
2977 | 2983 | ||
2978 | if (sid == fsec->sid && fsec->isid == isec->sid && | 2984 | if (sid == fsec->sid && fsec->isid == isec->sid && |
2979 | fsec->pseqno == avc_policy_seqno()) | 2985 | fsec->pseqno == avc_policy_seqno()) |
2980 | /* No change since dentry_open check. */ | 2986 | /* No change since file_open check. */ |
2981 | return 0; | 2987 | return 0; |
2982 | 2988 | ||
2983 | return selinux_revalidate_file_permission(file, mask); | 2989 | return selinux_revalidate_file_permission(file, mask); |
@@ -3236,15 +3242,13 @@ static int selinux_file_receive(struct file *file) | |||
3236 | return file_has_perm(cred, file, file_to_av(file)); | 3242 | return file_has_perm(cred, file, file_to_av(file)); |
3237 | } | 3243 | } |
3238 | 3244 | ||
3239 | static int selinux_dentry_open(struct file *file, const struct cred *cred) | 3245 | static int selinux_file_open(struct file *file, const struct cred *cred) |
3240 | { | 3246 | { |
3241 | struct file_security_struct *fsec; | 3247 | struct file_security_struct *fsec; |
3242 | struct inode *inode; | ||
3243 | struct inode_security_struct *isec; | 3248 | struct inode_security_struct *isec; |
3244 | 3249 | ||
3245 | inode = file->f_path.dentry->d_inode; | ||
3246 | fsec = file->f_security; | 3250 | fsec = file->f_security; |
3247 | isec = inode->i_security; | 3251 | isec = file->f_path.dentry->d_inode->i_security; |
3248 | /* | 3252 | /* |
3249 | * Save inode label and policy sequence number | 3253 | * Save inode label and policy sequence number |
3250 | * at open-time so that selinux_file_permission | 3254 | * at open-time so that selinux_file_permission |
@@ -3262,7 +3266,7 @@ static int selinux_dentry_open(struct file *file, const struct cred *cred) | |||
3262 | * new inode label or new policy. | 3266 | * new inode label or new policy. |
3263 | * This check is not redundant - do not remove. | 3267 | * This check is not redundant - do not remove. |
3264 | */ | 3268 | */ |
3265 | return inode_has_perm_noadp(cred, inode, open_file_to_av(file), 0); | 3269 | return path_has_perm(cred, &file->f_path, open_file_to_av(file)); |
3266 | } | 3270 | } |
3267 | 3271 | ||
3268 | /* task security operations */ | 3272 | /* task security operations */ |
@@ -3381,12 +3385,10 @@ static int selinux_kernel_module_request(char *kmod_name) | |||
3381 | { | 3385 | { |
3382 | u32 sid; | 3386 | u32 sid; |
3383 | struct common_audit_data ad; | 3387 | struct common_audit_data ad; |
3384 | struct selinux_audit_data sad = {0,}; | ||
3385 | 3388 | ||
3386 | sid = task_sid(current); | 3389 | sid = task_sid(current); |
3387 | 3390 | ||
3388 | COMMON_AUDIT_DATA_INIT(&ad, KMOD); | 3391 | ad.type = LSM_AUDIT_DATA_KMOD; |
3389 | ad.selinux_audit_data = &sad; | ||
3390 | ad.u.kmod_name = kmod_name; | 3392 | ad.u.kmod_name = kmod_name; |
3391 | 3393 | ||
3392 | return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM, | 3394 | return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM, |
@@ -3759,15 +3761,13 @@ static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms) | |||
3759 | { | 3761 | { |
3760 | struct sk_security_struct *sksec = sk->sk_security; | 3762 | struct sk_security_struct *sksec = sk->sk_security; |
3761 | struct common_audit_data ad; | 3763 | struct common_audit_data ad; |
3762 | struct selinux_audit_data sad = {0,}; | ||
3763 | struct lsm_network_audit net = {0,}; | 3764 | struct lsm_network_audit net = {0,}; |
3764 | u32 tsid = task_sid(task); | 3765 | u32 tsid = task_sid(task); |
3765 | 3766 | ||
3766 | if (sksec->sid == SECINITSID_KERNEL) | 3767 | if (sksec->sid == SECINITSID_KERNEL) |
3767 | return 0; | 3768 | return 0; |
3768 | 3769 | ||
3769 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 3770 | ad.type = LSM_AUDIT_DATA_NET; |
3770 | ad.selinux_audit_data = &sad; | ||
3771 | ad.u.net = &net; | 3771 | ad.u.net = &net; |
3772 | ad.u.net->sk = sk; | 3772 | ad.u.net->sk = sk; |
3773 | 3773 | ||
@@ -3847,7 +3847,6 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
3847 | char *addrp; | 3847 | char *addrp; |
3848 | struct sk_security_struct *sksec = sk->sk_security; | 3848 | struct sk_security_struct *sksec = sk->sk_security; |
3849 | struct common_audit_data ad; | 3849 | struct common_audit_data ad; |
3850 | struct selinux_audit_data sad = {0,}; | ||
3851 | struct lsm_network_audit net = {0,}; | 3850 | struct lsm_network_audit net = {0,}; |
3852 | struct sockaddr_in *addr4 = NULL; | 3851 | struct sockaddr_in *addr4 = NULL; |
3853 | struct sockaddr_in6 *addr6 = NULL; | 3852 | struct sockaddr_in6 *addr6 = NULL; |
@@ -3874,8 +3873,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
3874 | snum, &sid); | 3873 | snum, &sid); |
3875 | if (err) | 3874 | if (err) |
3876 | goto out; | 3875 | goto out; |
3877 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 3876 | ad.type = LSM_AUDIT_DATA_NET; |
3878 | ad.selinux_audit_data = &sad; | ||
3879 | ad.u.net = &net; | 3877 | ad.u.net = &net; |
3880 | ad.u.net->sport = htons(snum); | 3878 | ad.u.net->sport = htons(snum); |
3881 | ad.u.net->family = family; | 3879 | ad.u.net->family = family; |
@@ -3909,8 +3907,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
3909 | if (err) | 3907 | if (err) |
3910 | goto out; | 3908 | goto out; |
3911 | 3909 | ||
3912 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 3910 | ad.type = LSM_AUDIT_DATA_NET; |
3913 | ad.selinux_audit_data = &sad; | ||
3914 | ad.u.net = &net; | 3911 | ad.u.net = &net; |
3915 | ad.u.net->sport = htons(snum); | 3912 | ad.u.net->sport = htons(snum); |
3916 | ad.u.net->family = family; | 3913 | ad.u.net->family = family; |
@@ -3945,7 +3942,6 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, | |||
3945 | if (sksec->sclass == SECCLASS_TCP_SOCKET || | 3942 | if (sksec->sclass == SECCLASS_TCP_SOCKET || |
3946 | sksec->sclass == SECCLASS_DCCP_SOCKET) { | 3943 | sksec->sclass == SECCLASS_DCCP_SOCKET) { |
3947 | struct common_audit_data ad; | 3944 | struct common_audit_data ad; |
3948 | struct selinux_audit_data sad = {0,}; | ||
3949 | struct lsm_network_audit net = {0,}; | 3945 | struct lsm_network_audit net = {0,}; |
3950 | struct sockaddr_in *addr4 = NULL; | 3946 | struct sockaddr_in *addr4 = NULL; |
3951 | struct sockaddr_in6 *addr6 = NULL; | 3947 | struct sockaddr_in6 *addr6 = NULL; |
@@ -3971,8 +3967,7 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, | |||
3971 | perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ? | 3967 | perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ? |
3972 | TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT; | 3968 | TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT; |
3973 | 3969 | ||
3974 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 3970 | ad.type = LSM_AUDIT_DATA_NET; |
3975 | ad.selinux_audit_data = &sad; | ||
3976 | ad.u.net = &net; | 3971 | ad.u.net = &net; |
3977 | ad.u.net->dport = htons(snum); | 3972 | ad.u.net->dport = htons(snum); |
3978 | ad.u.net->family = sk->sk_family; | 3973 | ad.u.net->family = sk->sk_family; |
@@ -4064,12 +4059,10 @@ static int selinux_socket_unix_stream_connect(struct sock *sock, | |||
4064 | struct sk_security_struct *sksec_other = other->sk_security; | 4059 | struct sk_security_struct *sksec_other = other->sk_security; |
4065 | struct sk_security_struct *sksec_new = newsk->sk_security; | 4060 | struct sk_security_struct *sksec_new = newsk->sk_security; |
4066 | struct common_audit_data ad; | 4061 | struct common_audit_data ad; |
4067 | struct selinux_audit_data sad = {0,}; | ||
4068 | struct lsm_network_audit net = {0,}; | 4062 | struct lsm_network_audit net = {0,}; |
4069 | int err; | 4063 | int err; |
4070 | 4064 | ||
4071 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 4065 | ad.type = LSM_AUDIT_DATA_NET; |
4072 | ad.selinux_audit_data = &sad; | ||
4073 | ad.u.net = &net; | 4066 | ad.u.net = &net; |
4074 | ad.u.net->sk = other; | 4067 | ad.u.net->sk = other; |
4075 | 4068 | ||
@@ -4098,11 +4091,9 @@ static int selinux_socket_unix_may_send(struct socket *sock, | |||
4098 | struct sk_security_struct *ssec = sock->sk->sk_security; | 4091 | struct sk_security_struct *ssec = sock->sk->sk_security; |
4099 | struct sk_security_struct *osec = other->sk->sk_security; | 4092 | struct sk_security_struct *osec = other->sk->sk_security; |
4100 | struct common_audit_data ad; | 4093 | struct common_audit_data ad; |
4101 | struct selinux_audit_data sad = {0,}; | ||
4102 | struct lsm_network_audit net = {0,}; | 4094 | struct lsm_network_audit net = {0,}; |
4103 | 4095 | ||
4104 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 4096 | ad.type = LSM_AUDIT_DATA_NET; |
4105 | ad.selinux_audit_data = &sad; | ||
4106 | ad.u.net = &net; | 4097 | ad.u.net = &net; |
4107 | ad.u.net->sk = other->sk; | 4098 | ad.u.net->sk = other->sk; |
4108 | 4099 | ||
@@ -4140,12 +4131,10 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, | |||
4140 | struct sk_security_struct *sksec = sk->sk_security; | 4131 | struct sk_security_struct *sksec = sk->sk_security; |
4141 | u32 sk_sid = sksec->sid; | 4132 | u32 sk_sid = sksec->sid; |
4142 | struct common_audit_data ad; | 4133 | struct common_audit_data ad; |
4143 | struct selinux_audit_data sad = {0,}; | ||
4144 | struct lsm_network_audit net = {0,}; | 4134 | struct lsm_network_audit net = {0,}; |
4145 | char *addrp; | 4135 | char *addrp; |
4146 | 4136 | ||
4147 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 4137 | ad.type = LSM_AUDIT_DATA_NET; |
4148 | ad.selinux_audit_data = &sad; | ||
4149 | ad.u.net = &net; | 4138 | ad.u.net = &net; |
4150 | ad.u.net->netif = skb->skb_iif; | 4139 | ad.u.net->netif = skb->skb_iif; |
4151 | ad.u.net->family = family; | 4140 | ad.u.net->family = family; |
@@ -4175,7 +4164,6 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
4175 | u16 family = sk->sk_family; | 4164 | u16 family = sk->sk_family; |
4176 | u32 sk_sid = sksec->sid; | 4165 | u32 sk_sid = sksec->sid; |
4177 | struct common_audit_data ad; | 4166 | struct common_audit_data ad; |
4178 | struct selinux_audit_data sad = {0,}; | ||
4179 | struct lsm_network_audit net = {0,}; | 4167 | struct lsm_network_audit net = {0,}; |
4180 | char *addrp; | 4168 | char *addrp; |
4181 | u8 secmark_active; | 4169 | u8 secmark_active; |
@@ -4200,8 +4188,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
4200 | if (!secmark_active && !peerlbl_active) | 4188 | if (!secmark_active && !peerlbl_active) |
4201 | return 0; | 4189 | return 0; |
4202 | 4190 | ||
4203 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 4191 | ad.type = LSM_AUDIT_DATA_NET; |
4204 | ad.selinux_audit_data = &sad; | ||
4205 | ad.u.net = &net; | 4192 | ad.u.net = &net; |
4206 | ad.u.net->netif = skb->skb_iif; | 4193 | ad.u.net->netif = skb->skb_iif; |
4207 | ad.u.net->family = family; | 4194 | ad.u.net->family = family; |
@@ -4539,7 +4526,6 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, | |||
4539 | char *addrp; | 4526 | char *addrp; |
4540 | u32 peer_sid; | 4527 | u32 peer_sid; |
4541 | struct common_audit_data ad; | 4528 | struct common_audit_data ad; |
4542 | struct selinux_audit_data sad = {0,}; | ||
4543 | struct lsm_network_audit net = {0,}; | 4529 | struct lsm_network_audit net = {0,}; |
4544 | u8 secmark_active; | 4530 | u8 secmark_active; |
4545 | u8 netlbl_active; | 4531 | u8 netlbl_active; |
@@ -4557,8 +4543,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, | |||
4557 | if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0) | 4543 | if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0) |
4558 | return NF_DROP; | 4544 | return NF_DROP; |
4559 | 4545 | ||
4560 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 4546 | ad.type = LSM_AUDIT_DATA_NET; |
4561 | ad.selinux_audit_data = &sad; | ||
4562 | ad.u.net = &net; | 4547 | ad.u.net = &net; |
4563 | ad.u.net->netif = ifindex; | 4548 | ad.u.net->netif = ifindex; |
4564 | ad.u.net->family = family; | 4549 | ad.u.net->family = family; |
@@ -4648,7 +4633,6 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, | |||
4648 | struct sock *sk = skb->sk; | 4633 | struct sock *sk = skb->sk; |
4649 | struct sk_security_struct *sksec; | 4634 | struct sk_security_struct *sksec; |
4650 | struct common_audit_data ad; | 4635 | struct common_audit_data ad; |
4651 | struct selinux_audit_data sad = {0,}; | ||
4652 | struct lsm_network_audit net = {0,}; | 4636 | struct lsm_network_audit net = {0,}; |
4653 | char *addrp; | 4637 | char *addrp; |
4654 | u8 proto; | 4638 | u8 proto; |
@@ -4657,8 +4641,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, | |||
4657 | return NF_ACCEPT; | 4641 | return NF_ACCEPT; |
4658 | sksec = sk->sk_security; | 4642 | sksec = sk->sk_security; |
4659 | 4643 | ||
4660 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 4644 | ad.type = LSM_AUDIT_DATA_NET; |
4661 | ad.selinux_audit_data = &sad; | ||
4662 | ad.u.net = &net; | 4645 | ad.u.net = &net; |
4663 | ad.u.net->netif = ifindex; | 4646 | ad.u.net->netif = ifindex; |
4664 | ad.u.net->family = family; | 4647 | ad.u.net->family = family; |
@@ -4683,7 +4666,6 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, | |||
4683 | u32 peer_sid; | 4666 | u32 peer_sid; |
4684 | struct sock *sk; | 4667 | struct sock *sk; |
4685 | struct common_audit_data ad; | 4668 | struct common_audit_data ad; |
4686 | struct selinux_audit_data sad = {0,}; | ||
4687 | struct lsm_network_audit net = {0,}; | 4669 | struct lsm_network_audit net = {0,}; |
4688 | char *addrp; | 4670 | char *addrp; |
4689 | u8 secmark_active; | 4671 | u8 secmark_active; |
@@ -4730,8 +4712,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, | |||
4730 | secmark_perm = PACKET__SEND; | 4712 | secmark_perm = PACKET__SEND; |
4731 | } | 4713 | } |
4732 | 4714 | ||
4733 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 4715 | ad.type = LSM_AUDIT_DATA_NET; |
4734 | ad.selinux_audit_data = &sad; | ||
4735 | ad.u.net = &net; | 4716 | ad.u.net = &net; |
4736 | ad.u.net->netif = ifindex; | 4717 | ad.u.net->netif = ifindex; |
4737 | ad.u.net->family = family; | 4718 | ad.u.net->family = family; |
@@ -4849,13 +4830,11 @@ static int ipc_has_perm(struct kern_ipc_perm *ipc_perms, | |||
4849 | { | 4830 | { |
4850 | struct ipc_security_struct *isec; | 4831 | struct ipc_security_struct *isec; |
4851 | struct common_audit_data ad; | 4832 | struct common_audit_data ad; |
4852 | struct selinux_audit_data sad = {0,}; | ||
4853 | u32 sid = current_sid(); | 4833 | u32 sid = current_sid(); |
4854 | 4834 | ||
4855 | isec = ipc_perms->security; | 4835 | isec = ipc_perms->security; |
4856 | 4836 | ||
4857 | COMMON_AUDIT_DATA_INIT(&ad, IPC); | 4837 | ad.type = LSM_AUDIT_DATA_IPC; |
4858 | ad.selinux_audit_data = &sad; | ||
4859 | ad.u.ipc_id = ipc_perms->key; | 4838 | ad.u.ipc_id = ipc_perms->key; |
4860 | 4839 | ||
4861 | return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); | 4840 | return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); |
@@ -4876,7 +4855,6 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq) | |||
4876 | { | 4855 | { |
4877 | struct ipc_security_struct *isec; | 4856 | struct ipc_security_struct *isec; |
4878 | struct common_audit_data ad; | 4857 | struct common_audit_data ad; |
4879 | struct selinux_audit_data sad = {0,}; | ||
4880 | u32 sid = current_sid(); | 4858 | u32 sid = current_sid(); |
4881 | int rc; | 4859 | int rc; |
4882 | 4860 | ||
@@ -4886,8 +4864,7 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq) | |||
4886 | 4864 | ||
4887 | isec = msq->q_perm.security; | 4865 | isec = msq->q_perm.security; |
4888 | 4866 | ||
4889 | COMMON_AUDIT_DATA_INIT(&ad, IPC); | 4867 | ad.type = LSM_AUDIT_DATA_IPC; |
4890 | ad.selinux_audit_data = &sad; | ||
4891 | ad.u.ipc_id = msq->q_perm.key; | 4868 | ad.u.ipc_id = msq->q_perm.key; |
4892 | 4869 | ||
4893 | rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, | 4870 | rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, |
@@ -4908,13 +4885,11 @@ static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg) | |||
4908 | { | 4885 | { |
4909 | struct ipc_security_struct *isec; | 4886 | struct ipc_security_struct *isec; |
4910 | struct common_audit_data ad; | 4887 | struct common_audit_data ad; |
4911 | struct selinux_audit_data sad = {0,}; | ||
4912 | u32 sid = current_sid(); | 4888 | u32 sid = current_sid(); |
4913 | 4889 | ||
4914 | isec = msq->q_perm.security; | 4890 | isec = msq->q_perm.security; |
4915 | 4891 | ||
4916 | COMMON_AUDIT_DATA_INIT(&ad, IPC); | 4892 | ad.type = LSM_AUDIT_DATA_IPC; |
4917 | ad.selinux_audit_data = &sad; | ||
4918 | ad.u.ipc_id = msq->q_perm.key; | 4893 | ad.u.ipc_id = msq->q_perm.key; |
4919 | 4894 | ||
4920 | return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, | 4895 | return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, |
@@ -4954,7 +4929,6 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, | |||
4954 | struct ipc_security_struct *isec; | 4929 | struct ipc_security_struct *isec; |
4955 | struct msg_security_struct *msec; | 4930 | struct msg_security_struct *msec; |
4956 | struct common_audit_data ad; | 4931 | struct common_audit_data ad; |
4957 | struct selinux_audit_data sad = {0,}; | ||
4958 | u32 sid = current_sid(); | 4932 | u32 sid = current_sid(); |
4959 | int rc; | 4933 | int rc; |
4960 | 4934 | ||
@@ -4975,8 +4949,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, | |||
4975 | return rc; | 4949 | return rc; |
4976 | } | 4950 | } |
4977 | 4951 | ||
4978 | COMMON_AUDIT_DATA_INIT(&ad, IPC); | 4952 | ad.type = LSM_AUDIT_DATA_IPC; |
4979 | ad.selinux_audit_data = &sad; | ||
4980 | ad.u.ipc_id = msq->q_perm.key; | 4953 | ad.u.ipc_id = msq->q_perm.key; |
4981 | 4954 | ||
4982 | /* Can this process write to the queue? */ | 4955 | /* Can this process write to the queue? */ |
@@ -5001,15 +4974,13 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, | |||
5001 | struct ipc_security_struct *isec; | 4974 | struct ipc_security_struct *isec; |
5002 | struct msg_security_struct *msec; | 4975 | struct msg_security_struct *msec; |
5003 | struct common_audit_data ad; | 4976 | struct common_audit_data ad; |
5004 | struct selinux_audit_data sad = {0,}; | ||
5005 | u32 sid = task_sid(target); | 4977 | u32 sid = task_sid(target); |
5006 | int rc; | 4978 | int rc; |
5007 | 4979 | ||
5008 | isec = msq->q_perm.security; | 4980 | isec = msq->q_perm.security; |
5009 | msec = msg->security; | 4981 | msec = msg->security; |
5010 | 4982 | ||
5011 | COMMON_AUDIT_DATA_INIT(&ad, IPC); | 4983 | ad.type = LSM_AUDIT_DATA_IPC; |
5012 | ad.selinux_audit_data = &sad; | ||
5013 | ad.u.ipc_id = msq->q_perm.key; | 4984 | ad.u.ipc_id = msq->q_perm.key; |
5014 | 4985 | ||
5015 | rc = avc_has_perm(sid, isec->sid, | 4986 | rc = avc_has_perm(sid, isec->sid, |
@@ -5025,7 +4996,6 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp) | |||
5025 | { | 4996 | { |
5026 | struct ipc_security_struct *isec; | 4997 | struct ipc_security_struct *isec; |
5027 | struct common_audit_data ad; | 4998 | struct common_audit_data ad; |
5028 | struct selinux_audit_data sad = {0,}; | ||
5029 | u32 sid = current_sid(); | 4999 | u32 sid = current_sid(); |
5030 | int rc; | 5000 | int rc; |
5031 | 5001 | ||
@@ -5035,8 +5005,7 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp) | |||
5035 | 5005 | ||
5036 | isec = shp->shm_perm.security; | 5006 | isec = shp->shm_perm.security; |
5037 | 5007 | ||
5038 | COMMON_AUDIT_DATA_INIT(&ad, IPC); | 5008 | ad.type = LSM_AUDIT_DATA_IPC; |
5039 | ad.selinux_audit_data = &sad; | ||
5040 | ad.u.ipc_id = shp->shm_perm.key; | 5009 | ad.u.ipc_id = shp->shm_perm.key; |
5041 | 5010 | ||
5042 | rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM, | 5011 | rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM, |
@@ -5057,13 +5026,11 @@ static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg) | |||
5057 | { | 5026 | { |
5058 | struct ipc_security_struct *isec; | 5027 | struct ipc_security_struct *isec; |
5059 | struct common_audit_data ad; | 5028 | struct common_audit_data ad; |
5060 | struct selinux_audit_data sad = {0,}; | ||
5061 | u32 sid = current_sid(); | 5029 | u32 sid = current_sid(); |
5062 | 5030 | ||
5063 | isec = shp->shm_perm.security; | 5031 | isec = shp->shm_perm.security; |
5064 | 5032 | ||
5065 | COMMON_AUDIT_DATA_INIT(&ad, IPC); | 5033 | ad.type = LSM_AUDIT_DATA_IPC; |
5066 | ad.selinux_audit_data = &sad; | ||
5067 | ad.u.ipc_id = shp->shm_perm.key; | 5034 | ad.u.ipc_id = shp->shm_perm.key; |
5068 | 5035 | ||
5069 | return avc_has_perm(sid, isec->sid, SECCLASS_SHM, | 5036 | return avc_has_perm(sid, isec->sid, SECCLASS_SHM, |
@@ -5121,7 +5088,6 @@ static int selinux_sem_alloc_security(struct sem_array *sma) | |||
5121 | { | 5088 | { |
5122 | struct ipc_security_struct *isec; | 5089 | struct ipc_security_struct *isec; |
5123 | struct common_audit_data ad; | 5090 | struct common_audit_data ad; |
5124 | struct selinux_audit_data sad = {0,}; | ||
5125 | u32 sid = current_sid(); | 5091 | u32 sid = current_sid(); |
5126 | int rc; | 5092 | int rc; |
5127 | 5093 | ||
@@ -5131,8 +5097,7 @@ static int selinux_sem_alloc_security(struct sem_array *sma) | |||
5131 | 5097 | ||
5132 | isec = sma->sem_perm.security; | 5098 | isec = sma->sem_perm.security; |
5133 | 5099 | ||
5134 | COMMON_AUDIT_DATA_INIT(&ad, IPC); | 5100 | ad.type = LSM_AUDIT_DATA_IPC; |
5135 | ad.selinux_audit_data = &sad; | ||
5136 | ad.u.ipc_id = sma->sem_perm.key; | 5101 | ad.u.ipc_id = sma->sem_perm.key; |
5137 | 5102 | ||
5138 | rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM, | 5103 | rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM, |
@@ -5153,13 +5118,11 @@ static int selinux_sem_associate(struct sem_array *sma, int semflg) | |||
5153 | { | 5118 | { |
5154 | struct ipc_security_struct *isec; | 5119 | struct ipc_security_struct *isec; |
5155 | struct common_audit_data ad; | 5120 | struct common_audit_data ad; |
5156 | struct selinux_audit_data sad = {0,}; | ||
5157 | u32 sid = current_sid(); | 5121 | u32 sid = current_sid(); |
5158 | 5122 | ||
5159 | isec = sma->sem_perm.security; | 5123 | isec = sma->sem_perm.security; |
5160 | 5124 | ||
5161 | COMMON_AUDIT_DATA_INIT(&ad, IPC); | 5125 | ad.type = LSM_AUDIT_DATA_IPC; |
5162 | ad.selinux_audit_data = &sad; | ||
5163 | ad.u.ipc_id = sma->sem_perm.key; | 5126 | ad.u.ipc_id = sma->sem_perm.key; |
5164 | 5127 | ||
5165 | return avc_has_perm(sid, isec->sid, SECCLASS_SEM, | 5128 | return avc_has_perm(sid, isec->sid, SECCLASS_SEM, |
@@ -5339,8 +5302,23 @@ static int selinux_setprocattr(struct task_struct *p, | |||
5339 | } | 5302 | } |
5340 | error = security_context_to_sid(value, size, &sid); | 5303 | error = security_context_to_sid(value, size, &sid); |
5341 | if (error == -EINVAL && !strcmp(name, "fscreate")) { | 5304 | if (error == -EINVAL && !strcmp(name, "fscreate")) { |
5342 | if (!capable(CAP_MAC_ADMIN)) | 5305 | if (!capable(CAP_MAC_ADMIN)) { |
5306 | struct audit_buffer *ab; | ||
5307 | size_t audit_size; | ||
5308 | |||
5309 | /* We strip a nul only if it is at the end, otherwise the | ||
5310 | * context contains a nul and we should audit that */ | ||
5311 | if (str[size - 1] == '\0') | ||
5312 | audit_size = size - 1; | ||
5313 | else | ||
5314 | audit_size = size; | ||
5315 | ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR); | ||
5316 | audit_log_format(ab, "op=fscreate invalid_context="); | ||
5317 | audit_log_n_untrustedstring(ab, value, audit_size); | ||
5318 | audit_log_end(ab); | ||
5319 | |||
5343 | return error; | 5320 | return error; |
5321 | } | ||
5344 | error = security_context_to_sid_force(value, size, | 5322 | error = security_context_to_sid_force(value, size, |
5345 | &sid); | 5323 | &sid); |
5346 | } | 5324 | } |
@@ -5600,7 +5578,7 @@ static struct security_operations selinux_ops = { | |||
5600 | .file_send_sigiotask = selinux_file_send_sigiotask, | 5578 | .file_send_sigiotask = selinux_file_send_sigiotask, |
5601 | .file_receive = selinux_file_receive, | 5579 | .file_receive = selinux_file_receive, |
5602 | 5580 | ||
5603 | .dentry_open = selinux_dentry_open, | 5581 | .file_open = selinux_file_open, |
5604 | 5582 | ||
5605 | .task_create = selinux_task_create, | 5583 | .task_create = selinux_task_create, |
5606 | .cred_alloc_blank = selinux_cred_alloc_blank, | 5584 | .cred_alloc_blank = selinux_cred_alloc_blank, |
diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h index 1931370233d7..92d0ab561db8 100644 --- a/security/selinux/include/avc.h +++ b/security/selinux/include/avc.h | |||
@@ -49,7 +49,7 @@ struct avc_cache_stats { | |||
49 | /* | 49 | /* |
50 | * We only need this data after we have decided to send an audit message. | 50 | * We only need this data after we have decided to send an audit message. |
51 | */ | 51 | */ |
52 | struct selinux_late_audit_data { | 52 | struct selinux_audit_data { |
53 | u32 ssid; | 53 | u32 ssid; |
54 | u32 tsid; | 54 | u32 tsid; |
55 | u16 tclass; | 55 | u16 tclass; |
@@ -60,28 +60,86 @@ struct selinux_late_audit_data { | |||
60 | }; | 60 | }; |
61 | 61 | ||
62 | /* | 62 | /* |
63 | * We collect this at the beginning or during an selinux security operation | ||
64 | */ | ||
65 | struct selinux_audit_data { | ||
66 | /* | ||
67 | * auditdeny is a bit tricky and unintuitive. See the | ||
68 | * comments in avc.c for it's meaning and usage. | ||
69 | */ | ||
70 | u32 auditdeny; | ||
71 | struct selinux_late_audit_data *slad; | ||
72 | }; | ||
73 | |||
74 | /* | ||
75 | * AVC operations | 63 | * AVC operations |
76 | */ | 64 | */ |
77 | 65 | ||
78 | void __init avc_init(void); | 66 | void __init avc_init(void); |
79 | 67 | ||
80 | int avc_audit(u32 ssid, u32 tsid, | 68 | static inline u32 avc_audit_required(u32 requested, |
81 | u16 tclass, u32 requested, | 69 | struct av_decision *avd, |
82 | struct av_decision *avd, | 70 | int result, |
83 | int result, | 71 | u32 auditdeny, |
84 | struct common_audit_data *a, unsigned flags); | 72 | u32 *deniedp) |
73 | { | ||
74 | u32 denied, audited; | ||
75 | denied = requested & ~avd->allowed; | ||
76 | if (unlikely(denied)) { | ||
77 | audited = denied & avd->auditdeny; | ||
78 | /* | ||
79 | * auditdeny is TRICKY! Setting a bit in | ||
80 | * this field means that ANY denials should NOT be audited if | ||
81 | * the policy contains an explicit dontaudit rule for that | ||
82 | * permission. Take notice that this is unrelated to the | ||
83 | * actual permissions that were denied. As an example lets | ||
84 | * assume: | ||
85 | * | ||
86 | * denied == READ | ||
87 | * avd.auditdeny & ACCESS == 0 (not set means explicit rule) | ||
88 | * auditdeny & ACCESS == 1 | ||
89 | * | ||
90 | * We will NOT audit the denial even though the denied | ||
91 | * permission was READ and the auditdeny checks were for | ||
92 | * ACCESS | ||
93 | */ | ||
94 | if (auditdeny && !(auditdeny & avd->auditdeny)) | ||
95 | audited = 0; | ||
96 | } else if (result) | ||
97 | audited = denied = requested; | ||
98 | else | ||
99 | audited = requested & avd->auditallow; | ||
100 | *deniedp = denied; | ||
101 | return audited; | ||
102 | } | ||
103 | |||
104 | int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass, | ||
105 | u32 requested, u32 audited, u32 denied, | ||
106 | struct common_audit_data *a, | ||
107 | unsigned flags); | ||
108 | |||
109 | /** | ||
110 | * avc_audit - Audit the granting or denial of permissions. | ||
111 | * @ssid: source security identifier | ||
112 | * @tsid: target security identifier | ||
113 | * @tclass: target security class | ||
114 | * @requested: requested permissions | ||
115 | * @avd: access vector decisions | ||
116 | * @result: result from avc_has_perm_noaudit | ||
117 | * @a: auxiliary audit data | ||
118 | * @flags: VFS walk flags | ||
119 | * | ||
120 | * Audit the granting or denial of permissions in accordance | ||
121 | * with the policy. This function is typically called by | ||
122 | * avc_has_perm() after a permission check, but can also be | ||
123 | * called directly by callers who use avc_has_perm_noaudit() | ||
124 | * in order to separate the permission check from the auditing. | ||
125 | * For example, this separation is useful when the permission check must | ||
126 | * be performed under a lock, to allow the lock to be released | ||
127 | * before calling the auditing code. | ||
128 | */ | ||
129 | static inline int avc_audit(u32 ssid, u32 tsid, | ||
130 | u16 tclass, u32 requested, | ||
131 | struct av_decision *avd, | ||
132 | int result, | ||
133 | struct common_audit_data *a, unsigned flags) | ||
134 | { | ||
135 | u32 audited, denied; | ||
136 | audited = avc_audit_required(requested, avd, result, 0, &denied); | ||
137 | if (likely(!audited)) | ||
138 | return 0; | ||
139 | return slow_avc_audit(ssid, tsid, tclass, | ||
140 | requested, audited, denied, | ||
141 | a, flags); | ||
142 | } | ||
85 | 143 | ||
86 | #define AVC_STRICT 1 /* Ignore permissive mode. */ | 144 | #define AVC_STRICT 1 /* Ignore permissive mode. */ |
87 | int avc_has_perm_noaudit(u32 ssid, u32 tsid, | 145 | int avc_has_perm_noaudit(u32 ssid, u32 tsid, |
@@ -112,11 +170,7 @@ u32 avc_policy_seqno(void); | |||
112 | #define AVC_CALLBACK_AUDITDENY_ENABLE 64 | 170 | #define AVC_CALLBACK_AUDITDENY_ENABLE 64 |
113 | #define AVC_CALLBACK_AUDITDENY_DISABLE 128 | 171 | #define AVC_CALLBACK_AUDITDENY_DISABLE 128 |
114 | 172 | ||
115 | int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid, | 173 | int avc_add_callback(int (*callback)(u32 event), u32 events); |
116 | u16 tclass, u32 perms, | ||
117 | u32 *out_retained), | ||
118 | u32 events, u32 ssid, u32 tsid, | ||
119 | u16 tclass, u32 perms); | ||
120 | 174 | ||
121 | /* Exported to selinuxfs */ | 175 | /* Exported to selinuxfs */ |
122 | int avc_get_hash_stats(char *page); | 176 | int avc_get_hash_stats(char *page); |
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index d871e8ad2103..dde2005407aa 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h | |||
@@ -31,13 +31,15 @@ | |||
31 | #define POLICYDB_VERSION_BOUNDARY 24 | 31 | #define POLICYDB_VERSION_BOUNDARY 24 |
32 | #define POLICYDB_VERSION_FILENAME_TRANS 25 | 32 | #define POLICYDB_VERSION_FILENAME_TRANS 25 |
33 | #define POLICYDB_VERSION_ROLETRANS 26 | 33 | #define POLICYDB_VERSION_ROLETRANS 26 |
34 | #define POLICYDB_VERSION_NEW_OBJECT_DEFAULTS 27 | ||
35 | #define POLICYDB_VERSION_DEFAULT_TYPE 28 | ||
34 | 36 | ||
35 | /* Range of policy versions we understand*/ | 37 | /* Range of policy versions we understand*/ |
36 | #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE | 38 | #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE |
37 | #ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX | 39 | #ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX |
38 | #define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE | 40 | #define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE |
39 | #else | 41 | #else |
40 | #define POLICYDB_VERSION_MAX POLICYDB_VERSION_ROLETRANS | 42 | #define POLICYDB_VERSION_MAX POLICYDB_VERSION_DEFAULT_TYPE |
41 | #endif | 43 | #endif |
42 | 44 | ||
43 | /* Mask for just the mount related flags */ | 45 | /* Mask for just the mount related flags */ |
diff --git a/security/selinux/netif.c b/security/selinux/netif.c index 326f22cbe405..47a49d1a6f6a 100644 --- a/security/selinux/netif.c +++ b/security/selinux/netif.c | |||
@@ -252,8 +252,7 @@ static void sel_netif_flush(void) | |||
252 | spin_unlock_bh(&sel_netif_lock); | 252 | spin_unlock_bh(&sel_netif_lock); |
253 | } | 253 | } |
254 | 254 | ||
255 | static int sel_netif_avc_callback(u32 event, u32 ssid, u32 tsid, | 255 | static int sel_netif_avc_callback(u32 event) |
256 | u16 class, u32 perms, u32 *retained) | ||
257 | { | 256 | { |
258 | if (event == AVC_CALLBACK_RESET) { | 257 | if (event == AVC_CALLBACK_RESET) { |
259 | sel_netif_flush(); | 258 | sel_netif_flush(); |
@@ -292,8 +291,7 @@ static __init int sel_netif_init(void) | |||
292 | 291 | ||
293 | register_netdevice_notifier(&sel_netif_netdev_notifier); | 292 | register_netdevice_notifier(&sel_netif_netdev_notifier); |
294 | 293 | ||
295 | err = avc_add_callback(sel_netif_avc_callback, AVC_CALLBACK_RESET, | 294 | err = avc_add_callback(sel_netif_avc_callback, AVC_CALLBACK_RESET); |
296 | SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0); | ||
297 | if (err) | 295 | if (err) |
298 | panic("avc_add_callback() failed, error %d\n", err); | 296 | panic("avc_add_callback() failed, error %d\n", err); |
299 | 297 | ||
diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c index 86365857c088..28f911cdd7c7 100644 --- a/security/selinux/netnode.c +++ b/security/selinux/netnode.c | |||
@@ -297,8 +297,7 @@ static void sel_netnode_flush(void) | |||
297 | spin_unlock_bh(&sel_netnode_lock); | 297 | spin_unlock_bh(&sel_netnode_lock); |
298 | } | 298 | } |
299 | 299 | ||
300 | static int sel_netnode_avc_callback(u32 event, u32 ssid, u32 tsid, | 300 | static int sel_netnode_avc_callback(u32 event) |
301 | u16 class, u32 perms, u32 *retained) | ||
302 | { | 301 | { |
303 | if (event == AVC_CALLBACK_RESET) { | 302 | if (event == AVC_CALLBACK_RESET) { |
304 | sel_netnode_flush(); | 303 | sel_netnode_flush(); |
@@ -320,8 +319,7 @@ static __init int sel_netnode_init(void) | |||
320 | sel_netnode_hash[iter].size = 0; | 319 | sel_netnode_hash[iter].size = 0; |
321 | } | 320 | } |
322 | 321 | ||
323 | ret = avc_add_callback(sel_netnode_avc_callback, AVC_CALLBACK_RESET, | 322 | ret = avc_add_callback(sel_netnode_avc_callback, AVC_CALLBACK_RESET); |
324 | SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0); | ||
325 | if (ret != 0) | 323 | if (ret != 0) |
326 | panic("avc_add_callback() failed, error %d\n", ret); | 324 | panic("avc_add_callback() failed, error %d\n", ret); |
327 | 325 | ||
diff --git a/security/selinux/netport.c b/security/selinux/netport.c index 7b9eb1faf68b..d35379781c2c 100644 --- a/security/selinux/netport.c +++ b/security/selinux/netport.c | |||
@@ -234,8 +234,7 @@ static void sel_netport_flush(void) | |||
234 | spin_unlock_bh(&sel_netport_lock); | 234 | spin_unlock_bh(&sel_netport_lock); |
235 | } | 235 | } |
236 | 236 | ||
237 | static int sel_netport_avc_callback(u32 event, u32 ssid, u32 tsid, | 237 | static int sel_netport_avc_callback(u32 event) |
238 | u16 class, u32 perms, u32 *retained) | ||
239 | { | 238 | { |
240 | if (event == AVC_CALLBACK_RESET) { | 239 | if (event == AVC_CALLBACK_RESET) { |
241 | sel_netport_flush(); | 240 | sel_netport_flush(); |
@@ -257,8 +256,7 @@ static __init int sel_netport_init(void) | |||
257 | sel_netport_hash[iter].size = 0; | 256 | sel_netport_hash[iter].size = 0; |
258 | } | 257 | } |
259 | 258 | ||
260 | ret = avc_add_callback(sel_netport_avc_callback, AVC_CALLBACK_RESET, | 259 | ret = avc_add_callback(sel_netport_avc_callback, AVC_CALLBACK_RESET); |
261 | SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0); | ||
262 | if (ret != 0) | 260 | if (ret != 0) |
263 | panic("avc_add_callback() failed, error %d\n", ret); | 261 | panic("avc_add_callback() failed, error %d\n", ret); |
264 | 262 | ||
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index d7018bfa1f00..4e93f9ef970b 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c | |||
@@ -496,6 +496,7 @@ static const struct file_operations sel_policy_ops = { | |||
496 | .read = sel_read_policy, | 496 | .read = sel_read_policy, |
497 | .mmap = sel_mmap_policy, | 497 | .mmap = sel_mmap_policy, |
498 | .release = sel_release_policy, | 498 | .release = sel_release_policy, |
499 | .llseek = generic_file_llseek, | ||
499 | }; | 500 | }; |
500 | 501 | ||
501 | static ssize_t sel_write_load(struct file *file, const char __user *buf, | 502 | static ssize_t sel_write_load(struct file *file, const char __user *buf, |
@@ -1232,6 +1233,7 @@ static int sel_make_bools(void) | |||
1232 | kfree(bool_pending_names[i]); | 1233 | kfree(bool_pending_names[i]); |
1233 | kfree(bool_pending_names); | 1234 | kfree(bool_pending_names); |
1234 | kfree(bool_pending_values); | 1235 | kfree(bool_pending_values); |
1236 | bool_num = 0; | ||
1235 | bool_pending_names = NULL; | 1237 | bool_pending_names = NULL; |
1236 | bool_pending_values = NULL; | 1238 | bool_pending_values = NULL; |
1237 | 1239 | ||
@@ -1532,11 +1534,6 @@ static int sel_make_initcon_files(struct dentry *dir) | |||
1532 | return 0; | 1534 | return 0; |
1533 | } | 1535 | } |
1534 | 1536 | ||
1535 | static inline unsigned int sel_div(unsigned long a, unsigned long b) | ||
1536 | { | ||
1537 | return a / b - (a % b < 0); | ||
1538 | } | ||
1539 | |||
1540 | static inline unsigned long sel_class_to_ino(u16 class) | 1537 | static inline unsigned long sel_class_to_ino(u16 class) |
1541 | { | 1538 | { |
1542 | return (class * (SEL_VEC_MAX + 1)) | SEL_CLASS_INO_OFFSET; | 1539 | return (class * (SEL_VEC_MAX + 1)) | SEL_CLASS_INO_OFFSET; |
@@ -1544,7 +1541,7 @@ static inline unsigned long sel_class_to_ino(u16 class) | |||
1544 | 1541 | ||
1545 | static inline u16 sel_ino_to_class(unsigned long ino) | 1542 | static inline u16 sel_ino_to_class(unsigned long ino) |
1546 | { | 1543 | { |
1547 | return sel_div(ino & SEL_INO_MASK, SEL_VEC_MAX + 1); | 1544 | return (ino & SEL_INO_MASK) / (SEL_VEC_MAX + 1); |
1548 | } | 1545 | } |
1549 | 1546 | ||
1550 | static inline unsigned long sel_perm_to_ino(u16 class, u32 perm) | 1547 | static inline unsigned long sel_perm_to_ino(u16 class, u32 perm) |
@@ -1831,7 +1828,7 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) | |||
1831 | [SEL_REJECT_UNKNOWN] = {"reject_unknown", &sel_handle_unknown_ops, S_IRUGO}, | 1828 | [SEL_REJECT_UNKNOWN] = {"reject_unknown", &sel_handle_unknown_ops, S_IRUGO}, |
1832 | [SEL_DENY_UNKNOWN] = {"deny_unknown", &sel_handle_unknown_ops, S_IRUGO}, | 1829 | [SEL_DENY_UNKNOWN] = {"deny_unknown", &sel_handle_unknown_ops, S_IRUGO}, |
1833 | [SEL_STATUS] = {"status", &sel_handle_status_ops, S_IRUGO}, | 1830 | [SEL_STATUS] = {"status", &sel_handle_status_ops, S_IRUGO}, |
1834 | [SEL_POLICY] = {"policy", &sel_policy_ops, S_IRUSR}, | 1831 | [SEL_POLICY] = {"policy", &sel_policy_ops, S_IRUGO}, |
1835 | /* last one */ {""} | 1832 | /* last one */ {""} |
1836 | }; | 1833 | }; |
1837 | ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files); | 1834 | ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files); |
diff --git a/security/selinux/ss/context.h b/security/selinux/ss/context.h index 45e8fb0515f8..212e3479a0d9 100644 --- a/security/selinux/ss/context.h +++ b/security/selinux/ss/context.h | |||
@@ -74,6 +74,26 @@ out: | |||
74 | return rc; | 74 | return rc; |
75 | } | 75 | } |
76 | 76 | ||
77 | /* | ||
78 | * Sets both levels in the MLS range of 'dst' to the high level of 'src'. | ||
79 | */ | ||
80 | static inline int mls_context_cpy_high(struct context *dst, struct context *src) | ||
81 | { | ||
82 | int rc; | ||
83 | |||
84 | dst->range.level[0].sens = src->range.level[1].sens; | ||
85 | rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[1].cat); | ||
86 | if (rc) | ||
87 | goto out; | ||
88 | |||
89 | dst->range.level[1].sens = src->range.level[1].sens; | ||
90 | rc = ebitmap_cpy(&dst->range.level[1].cat, &src->range.level[1].cat); | ||
91 | if (rc) | ||
92 | ebitmap_destroy(&dst->range.level[0].cat); | ||
93 | out: | ||
94 | return rc; | ||
95 | } | ||
96 | |||
77 | static inline int mls_context_cmp(struct context *c1, struct context *c2) | 97 | static inline int mls_context_cmp(struct context *c1, struct context *c2) |
78 | { | 98 | { |
79 | return ((c1->range.level[0].sens == c2->range.level[0].sens) && | 99 | return ((c1->range.level[0].sens == c2->range.level[0].sens) && |
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c index fbf9c5816c71..40de8d3f208e 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c | |||
@@ -517,6 +517,8 @@ int mls_compute_sid(struct context *scontext, | |||
517 | { | 517 | { |
518 | struct range_trans rtr; | 518 | struct range_trans rtr; |
519 | struct mls_range *r; | 519 | struct mls_range *r; |
520 | struct class_datum *cladatum; | ||
521 | int default_range = 0; | ||
520 | 522 | ||
521 | if (!policydb.mls_enabled) | 523 | if (!policydb.mls_enabled) |
522 | return 0; | 524 | return 0; |
@@ -530,6 +532,28 @@ int mls_compute_sid(struct context *scontext, | |||
530 | r = hashtab_search(policydb.range_tr, &rtr); | 532 | r = hashtab_search(policydb.range_tr, &rtr); |
531 | if (r) | 533 | if (r) |
532 | return mls_range_set(newcontext, r); | 534 | return mls_range_set(newcontext, r); |
535 | |||
536 | if (tclass && tclass <= policydb.p_classes.nprim) { | ||
537 | cladatum = policydb.class_val_to_struct[tclass - 1]; | ||
538 | if (cladatum) | ||
539 | default_range = cladatum->default_range; | ||
540 | } | ||
541 | |||
542 | switch (default_range) { | ||
543 | case DEFAULT_SOURCE_LOW: | ||
544 | return mls_context_cpy_low(newcontext, scontext); | ||
545 | case DEFAULT_SOURCE_HIGH: | ||
546 | return mls_context_cpy_high(newcontext, scontext); | ||
547 | case DEFAULT_SOURCE_LOW_HIGH: | ||
548 | return mls_context_cpy(newcontext, scontext); | ||
549 | case DEFAULT_TARGET_LOW: | ||
550 | return mls_context_cpy_low(newcontext, tcontext); | ||
551 | case DEFAULT_TARGET_HIGH: | ||
552 | return mls_context_cpy_high(newcontext, tcontext); | ||
553 | case DEFAULT_TARGET_LOW_HIGH: | ||
554 | return mls_context_cpy(newcontext, tcontext); | ||
555 | } | ||
556 | |||
533 | /* Fallthrough */ | 557 | /* Fallthrough */ |
534 | case AVTAB_CHANGE: | 558 | case AVTAB_CHANGE: |
535 | if ((tclass == policydb.process_class) || (sock == true)) | 559 | if ((tclass == policydb.process_class) || (sock == true)) |
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index a7f61d52f05c..9cd9b7c661ec 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c | |||
@@ -133,6 +133,16 @@ static struct policydb_compat_info policydb_compat[] = { | |||
133 | .sym_num = SYM_NUM, | 133 | .sym_num = SYM_NUM, |
134 | .ocon_num = OCON_NUM, | 134 | .ocon_num = OCON_NUM, |
135 | }, | 135 | }, |
136 | { | ||
137 | .version = POLICYDB_VERSION_NEW_OBJECT_DEFAULTS, | ||
138 | .sym_num = SYM_NUM, | ||
139 | .ocon_num = OCON_NUM, | ||
140 | }, | ||
141 | { | ||
142 | .version = POLICYDB_VERSION_DEFAULT_TYPE, | ||
143 | .sym_num = SYM_NUM, | ||
144 | .ocon_num = OCON_NUM, | ||
145 | }, | ||
136 | }; | 146 | }; |
137 | 147 | ||
138 | static struct policydb_compat_info *policydb_lookup_compat(int version) | 148 | static struct policydb_compat_info *policydb_lookup_compat(int version) |
@@ -1306,6 +1316,23 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp) | |||
1306 | goto bad; | 1316 | goto bad; |
1307 | } | 1317 | } |
1308 | 1318 | ||
1319 | if (p->policyvers >= POLICYDB_VERSION_NEW_OBJECT_DEFAULTS) { | ||
1320 | rc = next_entry(buf, fp, sizeof(u32) * 3); | ||
1321 | if (rc) | ||
1322 | goto bad; | ||
1323 | |||
1324 | cladatum->default_user = le32_to_cpu(buf[0]); | ||
1325 | cladatum->default_role = le32_to_cpu(buf[1]); | ||
1326 | cladatum->default_range = le32_to_cpu(buf[2]); | ||
1327 | } | ||
1328 | |||
1329 | if (p->policyvers >= POLICYDB_VERSION_DEFAULT_TYPE) { | ||
1330 | rc = next_entry(buf, fp, sizeof(u32) * 1); | ||
1331 | if (rc) | ||
1332 | goto bad; | ||
1333 | cladatum->default_type = le32_to_cpu(buf[0]); | ||
1334 | } | ||
1335 | |||
1309 | rc = hashtab_insert(h, key, cladatum); | 1336 | rc = hashtab_insert(h, key, cladatum); |
1310 | if (rc) | 1337 | if (rc) |
1311 | goto bad; | 1338 | goto bad; |
@@ -2832,6 +2859,23 @@ static int class_write(void *vkey, void *datum, void *ptr) | |||
2832 | if (rc) | 2859 | if (rc) |
2833 | return rc; | 2860 | return rc; |
2834 | 2861 | ||
2862 | if (p->policyvers >= POLICYDB_VERSION_NEW_OBJECT_DEFAULTS) { | ||
2863 | buf[0] = cpu_to_le32(cladatum->default_user); | ||
2864 | buf[1] = cpu_to_le32(cladatum->default_role); | ||
2865 | buf[2] = cpu_to_le32(cladatum->default_range); | ||
2866 | |||
2867 | rc = put_entry(buf, sizeof(uint32_t), 3, fp); | ||
2868 | if (rc) | ||
2869 | return rc; | ||
2870 | } | ||
2871 | |||
2872 | if (p->policyvers >= POLICYDB_VERSION_DEFAULT_TYPE) { | ||
2873 | buf[0] = cpu_to_le32(cladatum->default_type); | ||
2874 | rc = put_entry(buf, sizeof(uint32_t), 1, fp); | ||
2875 | if (rc) | ||
2876 | return rc; | ||
2877 | } | ||
2878 | |||
2835 | return 0; | 2879 | return 0; |
2836 | } | 2880 | } |
2837 | 2881 | ||
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h index b846c0387180..da637471d4ce 100644 --- a/security/selinux/ss/policydb.h +++ b/security/selinux/ss/policydb.h | |||
@@ -60,6 +60,20 @@ struct class_datum { | |||
60 | struct symtab permissions; /* class-specific permission symbol table */ | 60 | struct symtab permissions; /* class-specific permission symbol table */ |
61 | struct constraint_node *constraints; /* constraints on class permissions */ | 61 | struct constraint_node *constraints; /* constraints on class permissions */ |
62 | struct constraint_node *validatetrans; /* special transition rules */ | 62 | struct constraint_node *validatetrans; /* special transition rules */ |
63 | /* Options how a new object user, role, and type should be decided */ | ||
64 | #define DEFAULT_SOURCE 1 | ||
65 | #define DEFAULT_TARGET 2 | ||
66 | char default_user; | ||
67 | char default_role; | ||
68 | char default_type; | ||
69 | /* Options how a new object range should be decided */ | ||
70 | #define DEFAULT_SOURCE_LOW 1 | ||
71 | #define DEFAULT_SOURCE_HIGH 2 | ||
72 | #define DEFAULT_SOURCE_LOW_HIGH 3 | ||
73 | #define DEFAULT_TARGET_LOW 4 | ||
74 | #define DEFAULT_TARGET_HIGH 5 | ||
75 | #define DEFAULT_TARGET_LOW_HIGH 6 | ||
76 | char default_range; | ||
63 | }; | 77 | }; |
64 | 78 | ||
65 | /* Role attributes */ | 79 | /* Role attributes */ |
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 185f849a26f6..4321b8fc8863 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
@@ -1018,9 +1018,11 @@ static int context_struct_to_string(struct context *context, char **scontext, u3 | |||
1018 | 1018 | ||
1019 | if (context->len) { | 1019 | if (context->len) { |
1020 | *scontext_len = context->len; | 1020 | *scontext_len = context->len; |
1021 | *scontext = kstrdup(context->str, GFP_ATOMIC); | 1021 | if (scontext) { |
1022 | if (!(*scontext)) | 1022 | *scontext = kstrdup(context->str, GFP_ATOMIC); |
1023 | return -ENOMEM; | 1023 | if (!(*scontext)) |
1024 | return -ENOMEM; | ||
1025 | } | ||
1024 | return 0; | 1026 | return 0; |
1025 | } | 1027 | } |
1026 | 1028 | ||
@@ -1389,6 +1391,7 @@ static int security_compute_sid(u32 ssid, | |||
1389 | u32 *out_sid, | 1391 | u32 *out_sid, |
1390 | bool kern) | 1392 | bool kern) |
1391 | { | 1393 | { |
1394 | struct class_datum *cladatum = NULL; | ||
1392 | struct context *scontext = NULL, *tcontext = NULL, newcontext; | 1395 | struct context *scontext = NULL, *tcontext = NULL, newcontext; |
1393 | struct role_trans *roletr = NULL; | 1396 | struct role_trans *roletr = NULL; |
1394 | struct avtab_key avkey; | 1397 | struct avtab_key avkey; |
@@ -1437,12 +1440,20 @@ static int security_compute_sid(u32 ssid, | |||
1437 | goto out_unlock; | 1440 | goto out_unlock; |
1438 | } | 1441 | } |
1439 | 1442 | ||
1443 | if (tclass && tclass <= policydb.p_classes.nprim) | ||
1444 | cladatum = policydb.class_val_to_struct[tclass - 1]; | ||
1445 | |||
1440 | /* Set the user identity. */ | 1446 | /* Set the user identity. */ |
1441 | switch (specified) { | 1447 | switch (specified) { |
1442 | case AVTAB_TRANSITION: | 1448 | case AVTAB_TRANSITION: |
1443 | case AVTAB_CHANGE: | 1449 | case AVTAB_CHANGE: |
1444 | /* Use the process user identity. */ | 1450 | if (cladatum && cladatum->default_user == DEFAULT_TARGET) { |
1445 | newcontext.user = scontext->user; | 1451 | newcontext.user = tcontext->user; |
1452 | } else { | ||
1453 | /* notice this gets both DEFAULT_SOURCE and unset */ | ||
1454 | /* Use the process user identity. */ | ||
1455 | newcontext.user = scontext->user; | ||
1456 | } | ||
1446 | break; | 1457 | break; |
1447 | case AVTAB_MEMBER: | 1458 | case AVTAB_MEMBER: |
1448 | /* Use the related object owner. */ | 1459 | /* Use the related object owner. */ |
@@ -1450,16 +1461,31 @@ static int security_compute_sid(u32 ssid, | |||
1450 | break; | 1461 | break; |
1451 | } | 1462 | } |
1452 | 1463 | ||
1453 | /* Set the role and type to default values. */ | 1464 | /* Set the role to default values. */ |
1454 | if ((tclass == policydb.process_class) || (sock == true)) { | 1465 | if (cladatum && cladatum->default_role == DEFAULT_SOURCE) { |
1455 | /* Use the current role and type of process. */ | ||
1456 | newcontext.role = scontext->role; | 1466 | newcontext.role = scontext->role; |
1457 | newcontext.type = scontext->type; | 1467 | } else if (cladatum && cladatum->default_role == DEFAULT_TARGET) { |
1468 | newcontext.role = tcontext->role; | ||
1458 | } else { | 1469 | } else { |
1459 | /* Use the well-defined object role. */ | 1470 | if ((tclass == policydb.process_class) || (sock == true)) |
1460 | newcontext.role = OBJECT_R_VAL; | 1471 | newcontext.role = scontext->role; |
1461 | /* Use the type of the related object. */ | 1472 | else |
1473 | newcontext.role = OBJECT_R_VAL; | ||
1474 | } | ||
1475 | |||
1476 | /* Set the type to default values. */ | ||
1477 | if (cladatum && cladatum->default_type == DEFAULT_SOURCE) { | ||
1478 | newcontext.type = scontext->type; | ||
1479 | } else if (cladatum && cladatum->default_type == DEFAULT_TARGET) { | ||
1462 | newcontext.type = tcontext->type; | 1480 | newcontext.type = tcontext->type; |
1481 | } else { | ||
1482 | if ((tclass == policydb.process_class) || (sock == true)) { | ||
1483 | /* Use the type of process. */ | ||
1484 | newcontext.type = scontext->type; | ||
1485 | } else { | ||
1486 | /* Use the type of the related object. */ | ||
1487 | newcontext.type = tcontext->type; | ||
1488 | } | ||
1463 | } | 1489 | } |
1464 | 1490 | ||
1465 | /* Look for a type transition/member/change rule. */ | 1491 | /* Look for a type transition/member/change rule. */ |
@@ -3018,8 +3044,7 @@ out: | |||
3018 | 3044 | ||
3019 | static int (*aurule_callback)(void) = audit_update_lsm_rules; | 3045 | static int (*aurule_callback)(void) = audit_update_lsm_rules; |
3020 | 3046 | ||
3021 | static int aurule_avc_callback(u32 event, u32 ssid, u32 tsid, | 3047 | static int aurule_avc_callback(u32 event) |
3022 | u16 class, u32 perms, u32 *retained) | ||
3023 | { | 3048 | { |
3024 | int err = 0; | 3049 | int err = 0; |
3025 | 3050 | ||
@@ -3032,8 +3057,7 @@ static int __init aurule_init(void) | |||
3032 | { | 3057 | { |
3033 | int err; | 3058 | int err; |
3034 | 3059 | ||
3035 | err = avc_add_callback(aurule_avc_callback, AVC_CALLBACK_RESET, | 3060 | err = avc_add_callback(aurule_avc_callback, AVC_CALLBACK_RESET); |
3036 | SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0); | ||
3037 | if (err) | 3061 | if (err) |
3038 | panic("avc_add_callback() failed, error %d\n", err); | 3062 | panic("avc_add_callback() failed, error %d\n", err); |
3039 | 3063 | ||
diff --git a/security/smack/smack.h b/security/smack/smack.h index 5e031a2e4c36..cc361b8f3d13 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h | |||
@@ -304,7 +304,7 @@ void smack_log(char *subject_label, char *object_label, | |||
304 | static inline void smk_ad_init(struct smk_audit_info *a, const char *func, | 304 | static inline void smk_ad_init(struct smk_audit_info *a, const char *func, |
305 | char type) | 305 | char type) |
306 | { | 306 | { |
307 | memset(a, 0, sizeof(*a)); | 307 | memset(&a->sad, 0, sizeof(a->sad)); |
308 | a->a.type = type; | 308 | a->a.type = type; |
309 | a->a.smack_audit_data = &a->sad; | 309 | a->a.smack_audit_data = &a->sad; |
310 | a->a.smack_audit_data->function = func; | 310 | a->a.smack_audit_data->function = func; |
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 952b1f41fc78..d583c0545808 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
@@ -1359,7 +1359,7 @@ static int smack_file_receive(struct file *file) | |||
1359 | } | 1359 | } |
1360 | 1360 | ||
1361 | /** | 1361 | /** |
1362 | * smack_dentry_open - Smack dentry open processing | 1362 | * smack_file_open - Smack dentry open processing |
1363 | * @file: the object | 1363 | * @file: the object |
1364 | * @cred: unused | 1364 | * @cred: unused |
1365 | * | 1365 | * |
@@ -1367,7 +1367,7 @@ static int smack_file_receive(struct file *file) | |||
1367 | * | 1367 | * |
1368 | * Returns 0 | 1368 | * Returns 0 |
1369 | */ | 1369 | */ |
1370 | static int smack_dentry_open(struct file *file, const struct cred *cred) | 1370 | static int smack_file_open(struct file *file, const struct cred *cred) |
1371 | { | 1371 | { |
1372 | struct inode_smack *isp = file->f_path.dentry->d_inode->i_security; | 1372 | struct inode_smack *isp = file->f_path.dentry->d_inode->i_security; |
1373 | 1373 | ||
@@ -3487,7 +3487,7 @@ struct security_operations smack_ops = { | |||
3487 | .file_send_sigiotask = smack_file_send_sigiotask, | 3487 | .file_send_sigiotask = smack_file_send_sigiotask, |
3488 | .file_receive = smack_file_receive, | 3488 | .file_receive = smack_file_receive, |
3489 | 3489 | ||
3490 | .dentry_open = smack_dentry_open, | 3490 | .file_open = smack_file_open, |
3491 | 3491 | ||
3492 | .cred_alloc_blank = smack_cred_alloc_blank, | 3492 | .cred_alloc_blank = smack_cred_alloc_blank, |
3493 | .cred_free = smack_cred_free, | 3493 | .cred_free = smack_cred_free, |
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index 620d37c159a3..c2d04a50f76a 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c | |||
@@ -319,14 +319,14 @@ static int tomoyo_file_fcntl(struct file *file, unsigned int cmd, | |||
319 | } | 319 | } |
320 | 320 | ||
321 | /** | 321 | /** |
322 | * tomoyo_dentry_open - Target for security_dentry_open(). | 322 | * tomoyo_file_open - Target for security_file_open(). |
323 | * | 323 | * |
324 | * @f: Pointer to "struct file". | 324 | * @f: Pointer to "struct file". |
325 | * @cred: Pointer to "struct cred". | 325 | * @cred: Pointer to "struct cred". |
326 | * | 326 | * |
327 | * Returns 0 on success, negative value otherwise. | 327 | * Returns 0 on success, negative value otherwise. |
328 | */ | 328 | */ |
329 | static int tomoyo_dentry_open(struct file *f, const struct cred *cred) | 329 | static int tomoyo_file_open(struct file *f, const struct cred *cred) |
330 | { | 330 | { |
331 | int flags = f->f_flags; | 331 | int flags = f->f_flags; |
332 | /* Don't check read permission here if called from do_execve(). */ | 332 | /* Don't check read permission here if called from do_execve(). */ |
@@ -510,7 +510,7 @@ static struct security_operations tomoyo_security_ops = { | |||
510 | .bprm_set_creds = tomoyo_bprm_set_creds, | 510 | .bprm_set_creds = tomoyo_bprm_set_creds, |
511 | .bprm_check_security = tomoyo_bprm_check_security, | 511 | .bprm_check_security = tomoyo_bprm_check_security, |
512 | .file_fcntl = tomoyo_file_fcntl, | 512 | .file_fcntl = tomoyo_file_fcntl, |
513 | .dentry_open = tomoyo_dentry_open, | 513 | .file_open = tomoyo_file_open, |
514 | .path_truncate = tomoyo_path_truncate, | 514 | .path_truncate = tomoyo_path_truncate, |
515 | .path_unlink = tomoyo_path_unlink, | 515 | .path_unlink = tomoyo_path_unlink, |
516 | .path_mkdir = tomoyo_path_mkdir, | 516 | .path_mkdir = tomoyo_path_mkdir, |