Per pull request, for 3.5.
Unified · Split
| @@ -681,7 +681,7 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, · 680 unmodified lines | ||
| 681 | 681 | |
| 682 | 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 | 685 | if (error) |
| 686 | 686 | goto cleanup_all; |
| 687 | 687 | |
| @@ -53,7 +53,6 @@ struct common_audit_data { · 52 unmodified lines | ||
| 53 | 53 | #define LSM_AUDIT_DATA_KMOD 8 |
| 54 | 54 | #define LSM_AUDIT_DATA_INODE 9 |
| 55 | 55 | #define LSM_AUDIT_DATA_DENTRY 10 |
| 56 | − struct task_struct *tsk; | |
| 57 | 56 | union { |
| 58 | 57 | struct path path; |
| 59 | 58 | struct dentry *dentry; |
| @@ -93,11 +92,6 @@ int ipv4_skb_to_auditdata(struct sk_buff *skb, · 33 unmodified lines | ||
| 93 | 92 | int ipv6_skb_to_auditdata(struct sk_buff *skb, |
| 94 | 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 | 95 | void common_lsm_audit(struct common_audit_data *a, |
| 102 | 96 | void (*pre_audit)(struct audit_buffer *, void *), |
| 103 | 97 | void (*post_audit)(struct audit_buffer *, void *)); |
| @@ -640,10 +640,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) · 639 unmodified lines | ||
| 640 | 640 | * to receive an open file descriptor via socket IPC. |
| 641 | 641 | * @file contains the file structure being received. |
| 642 | 642 | * Return 0 if permission is granted. |
| 643 | − * | |
| 644 | − * Security hook for dentry | |
| 645 | − * | |
| 646 | − * @dentry_open | |
| 643 | + * @file_open | |
| 647 | 644 | * Save open-time permission checking state for later use upon |
| 648 | 645 | * file_permission, and recheck access if anything has changed |
| 649 | 646 | * since inode_permission. |
| @@ -1498,7 +1495,7 @@ struct security_operations { · 848 unmodified lines | ||
| 1498 | 1495 | int (*file_send_sigiotask) (struct task_struct *tsk, |
| 1499 | 1496 | struct fown_struct *fown, int sig); |
| 1500 | 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 | 1500 | int (*task_create) (unsigned long clone_flags); |
| 1504 | 1501 | void (*task_free) (struct task_struct *task); |
| @@ -1757,7 +1754,7 @@ int security_file_set_fowner(struct file *file); · 252 unmodified lines | ||
| 1757 | 1754 | int security_file_send_sigiotask(struct task_struct *tsk, |
| 1758 | 1755 | struct fown_struct *fown, int sig); |
| 1759 | 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 | 1758 | int security_task_create(unsigned long clone_flags); |
| 1762 | 1759 | void security_task_free(struct task_struct *task); |
| 1763 | 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) · 464 unmodified lines | ||
| 2228 | 2225 | return 0; |
| 2229 | 2226 | } |
| 2230 | 2227 | |
| 2231 | −static inline int security_dentry_open(struct file *file, | |
| 2232 | − const struct cred *cred) | |
| 2228 | +static inline int security_file_open(struct file *file, | |
| 2229 | + const struct cred *cred) | |
| 2233 | 2230 | { |
| 2234 | 2231 | return 0; |
| 2235 | 2232 | } |
| @@ -26,6 +26,7 @@ · 25 unmodified lines | ||
| 26 | 26 | #include <linux/cache.h> |
| 27 | 27 | #include <linux/audit.h> |
| 28 | 28 | #include <net/dst.h> |
| 29 | +#include <net/flow.h> | |
| 29 | 30 | #include <net/xfrm.h> |
| 30 | 31 | #include <net/ip.h> |
| 31 | 32 | #ifdef CONFIG_XFRM_STATISTICS |
| @@ -111,7 +111,7 @@ static const char *const aa_audit_type[] = { · 110 unmodified lines | ||
| 111 | 111 | static void audit_pre(struct audit_buffer *ab, void *ca) |
| 112 | 112 | { |
| 113 | 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 | 116 | if (aa_g_audit_header) { |
| 117 | 117 | audit_log_format(ab, "apparmor="); |
| @@ -149,6 +149,12 @@ static void audit_pre(struct audit_buffer *ab, void *ca) · 31 unmodified lines | ||
| 149 | 149 | audit_log_format(ab, " name="); |
| 150 | 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, · 50 unmodified lines | ||
| 205 | 211 | aa_audit_msg(type, sa, cb); |
| 206 | 212 | |
| 207 | 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 | 217 | if (sa->aad->type == AUDIT_APPARMOR_ALLOWED) |
| 211 | 218 | return complain_error(sa->aad->error); |
| @@ -65,10 +65,10 @@ static int audit_caps(struct aa_profile *profile, struct task_struct *task, · 64 unmodified lines | ||
| 65 | 65 | int type = AUDIT_APPARMOR_AUTO; |
| 66 | 66 | struct common_audit_data sa; |
| 67 | 67 | struct apparmor_audit_data aad = {0,}; |
| 68 | − COMMON_AUDIT_DATA_INIT(&sa, CAP); | |
| 68 | + sa.type = LSM_AUDIT_DATA_CAP; | |
| 69 | 69 | sa.aad = &aad; |
| 70 | − sa.tsk = task; | |
| 71 | 70 | sa.u.cap = cap; |
| 71 | + sa.aad->tsk = task; | |
| 72 | 72 | sa.aad->op = OP_CAPABLE; |
| 73 | 73 | sa.aad->error = error; |
| 74 | 74 | |
| @@ -108,7 +108,7 @@ int aa_audit_file(struct aa_profile *profile, struct file_perms *perms, · 107 unmodified lines | ||
| 108 | 108 | int type = AUDIT_APPARMOR_AUTO; |
| 109 | 109 | struct common_audit_data sa; |
| 110 | 110 | struct apparmor_audit_data aad = {0,}; |
| 111 | − COMMON_AUDIT_DATA_INIT(&sa, NONE); | |
| 111 | + sa.type = LSM_AUDIT_DATA_NONE; | |
| 112 | 112 | sa.aad = &aad; |
| 113 | 113 | aad.op = op, |
| 114 | 114 | aad.fs.request = request; |
| @@ -110,6 +110,7 @@ struct apparmor_audit_data { · 109 unmodified lines | ||
| 110 | 110 | void *profile; |
| 111 | 111 | const char *name; |
| 112 | 112 | const char *info; |
| 113 | + struct task_struct *tsk; | |
| 113 | 114 | union { |
| 114 | 115 | void *target; |
| 115 | 116 | struct { |
| @@ -42,7 +42,7 @@ static int aa_audit_ptrace(struct aa_profile *profile, · 41 unmodified lines | ||
| 42 | 42 | { |
| 43 | 43 | struct common_audit_data sa; |
| 44 | 44 | struct apparmor_audit_data aad = {0,}; |
| 45 | − COMMON_AUDIT_DATA_INIT(&sa, NONE); | |
| 45 | + sa.type = LSM_AUDIT_DATA_NONE; | |
| 46 | 46 | sa.aad = &aad; |
| 47 | 47 | aad.op = OP_PTRACE; |
| 48 | 48 | aad.target = target; |
| @@ -66,7 +66,7 @@ void aa_info_message(const char *str) · 65 unmodified lines | ||
| 66 | 66 | if (audit_enabled) { |
| 67 | 67 | struct common_audit_data sa; |
| 68 | 68 | struct apparmor_audit_data aad = {0,}; |
| 69 | − COMMON_AUDIT_DATA_INIT(&sa, NONE); | |
| 69 | + sa.type = LSM_AUDIT_DATA_NONE; | |
| 70 | 70 | sa.aad = &aad; |
| 71 | 71 | aad.info = str; |
| 72 | 72 | aa_audit_msg(AUDIT_APPARMOR_STATUS, &sa, NULL); |
| @@ -373,7 +373,7 @@ static int apparmor_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) · 372 unmodified lines | ||
| 373 | 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 | 378 | struct aa_file_cxt *fcxt = file->f_security; |
| 379 | 379 | struct aa_profile *profile; |
| @@ -589,7 +589,7 @@ static int apparmor_setprocattr(struct task_struct *task, char *name, · 209 unmodified lines | ||
| 589 | 589 | } else { |
| 590 | 590 | struct common_audit_data sa; |
| 591 | 591 | struct apparmor_audit_data aad = {0,}; |
| 592 | − COMMON_AUDIT_DATA_INIT(&sa, NONE); | |
| 592 | + sa.type = LSM_AUDIT_DATA_NONE; | |
| 593 | 593 | sa.aad = &aad; |
| 594 | 594 | aad.op = OP_SETPROCATTR; |
| 595 | 595 | aad.info = name; |
| @@ -640,9 +640,9 @@ static struct security_operations apparmor_ops = { · 44 unmodified lines | ||
| 640 | 640 | .path_chmod = apparmor_path_chmod, |
| 641 | 641 | .path_chown = apparmor_path_chown, |
| 642 | 642 | .path_truncate = apparmor_path_truncate, |
| 643 | − .dentry_open = apparmor_dentry_open, | |
| 644 | 643 | .inode_getattr = apparmor_inode_getattr, |
| 645 | 644 | |
| 645 | + .file_open = apparmor_file_open, | |
| 646 | 646 | .file_permission = apparmor_file_permission, |
| 647 | 647 | .file_alloc_security = apparmor_file_alloc_security, |
| 648 | 648 | .file_free_security = apparmor_file_free_security, |
| @@ -969,7 +969,7 @@ static int audit_policy(int op, gfp_t gfp, const char *name, const char *info, · 968 unmodified lines | ||
| 969 | 969 | { |
| 970 | 970 | struct common_audit_data sa; |
| 971 | 971 | struct apparmor_audit_data aad = {0,}; |
| 972 | − COMMON_AUDIT_DATA_INIT(&sa, NONE); | |
| 972 | + sa.type = LSM_AUDIT_DATA_NONE; | |
| 973 | 973 | sa.aad = &aad; |
| 974 | 974 | aad.op = op; |
| 975 | 975 | aad.name = name; |
| @@ -95,7 +95,7 @@ static int audit_iface(struct aa_profile *new, const char *name, · 94 unmodified lines | ||
| 95 | 95 | struct aa_profile *profile = __aa_current_profile(); |
| 96 | 96 | struct common_audit_data sa; |
| 97 | 97 | struct apparmor_audit_data aad = {0,}; |
| 98 | − COMMON_AUDIT_DATA_INIT(&sa, NONE); | |
| 98 | + sa.type = LSM_AUDIT_DATA_NONE; | |
| 99 | 99 | sa.aad = &aad; |
| 100 | 100 | if (e) |
| 101 | 101 | aad.iface.pos = e->pos - e->start; |
| @@ -52,7 +52,7 @@ static int audit_resource(struct aa_profile *profile, unsigned int resource, · 51 unmodified lines | ||
| 52 | 52 | struct common_audit_data sa; |
| 53 | 53 | struct apparmor_audit_data aad = {0,}; |
| 54 | 54 | |
| 55 | − COMMON_AUDIT_DATA_INIT(&sa, NONE); | |
| 55 | + sa.type = LSM_AUDIT_DATA_NONE; | |
| 56 | 56 | sa.aad = &aad; |
| 57 | 57 | aad.op = OP_SETRLIMIT, |
| 58 | 58 | aad.rlim.rlim = resource; |
| @@ -348,7 +348,7 @@ static int cap_file_receive(struct file *file) · 347 unmodified lines | ||
| 348 | 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 | 353 | return 0; |
| 354 | 354 | } |
| @@ -956,7 +956,7 @@ void __init security_fixup_ops(struct security_operations *ops) · 601 unmodified lines | ||
| 956 | 956 | set_to_cap_if_null(ops, file_set_fowner); |
| 957 | 957 | set_to_cap_if_null(ops, file_send_sigiotask); |
| 958 | 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 | 960 | set_to_cap_if_null(ops, task_create); |
| 961 | 961 | set_to_cap_if_null(ops, task_free); |
| 962 | 962 | set_to_cap_if_null(ops, cred_alloc_blank); |
| @@ -213,12 +213,15 @@ static void dump_common_audit_data(struct audit_buffer *ab, · 212 unmodified lines | ||
| 213 | 213 | { |
| 214 | 214 | struct task_struct *tsk = current; |
| 215 | 215 | |
| 216 | − if (a->tsk) | |
| 217 | − tsk = a->tsk; | |
| 218 | − if (tsk && tsk->pid) { | |
| 219 | − audit_log_format(ab, " pid=%d comm=", tsk->pid); | |
| 220 | − audit_log_untrustedstring(ab, tsk->comm); | |
| 221 | − } | |
| 216 | + /* | |
| 217 | + * To keep stack sizes in check force programers to notice if they | |
| 218 | + * start making this union too large! See struct lsm_network_audit | |
| 219 | + * as an example of how to deal with large data. | |
| 220 | + */ | |
| 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 | 226 | switch (a->type) { |
| 224 | 227 | case LSM_AUDIT_DATA_NONE: |
| @@ -701,11 +701,11 @@ int security_file_receive(struct file *file) · 700 unmodified lines | ||
| 701 | 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 | 706 | int ret; |
| 707 | 707 | |
| 708 | − ret = security_ops->dentry_open(file, cred); | |
| 708 | + ret = security_ops->file_open(file, cred); | |
| 709 | 709 | if (ret) |
| 710 | 710 | return ret; |
| 711 | 711 | |
| @@ -65,14 +65,8 @@ struct avc_cache { · 64 unmodified lines | ||
| 65 | 65 | }; |
| 66 | 66 | |
| 67 | 67 | struct avc_callback_node { |
| 68 | − int (*callback) (u32 event, u32 ssid, u32 tsid, | |
| 69 | − u16 tclass, u32 perms, | |
| 70 | − u32 *out_retained); | |
| 68 | + int (*callback) (u32 event); | |
| 71 | 69 | u32 events; |
| 72 | − u32 ssid; | |
| 73 | − u32 tsid; | |
| 74 | − u16 tclass; | |
| 75 | − u32 perms; | |
| 76 | 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) · 357 unmodified lines | ||
| 436 | 430 | { |
| 437 | 431 | struct common_audit_data *ad = a; |
| 438 | 432 | audit_log_format(ab, "avc: %s ", |
| 439 | − ad->selinux_audit_data->slad->denied ? "denied" : "granted"); | |
| 440 | − avc_dump_av(ab, ad->selinux_audit_data->slad->tclass, | |
| 441 | − ad->selinux_audit_data->slad->audited); | |
| 433 | + ad->selinux_audit_data->denied ? "denied" : "granted"); | |
| 434 | + avc_dump_av(ab, ad->selinux_audit_data->tclass, | |
| 435 | + ad->selinux_audit_data->audited); | |
| 442 | 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) · 7 unmodified lines | ||
| 452 | 446 | { |
| 453 | 447 | struct common_audit_data *ad = a; |
| 454 | 448 | audit_log_format(ab, " "); |
| 455 | − avc_dump_query(ab, ad->selinux_audit_data->slad->ssid, | |
| 456 | − ad->selinux_audit_data->slad->tsid, | |
| 457 | − ad->selinux_audit_data->slad->tclass); | |
| 449 | + avc_dump_query(ab, ad->selinux_audit_data->ssid, | |
| 450 | + ad->selinux_audit_data->tsid, | |
| 451 | + ad->selinux_audit_data->tclass); | |
| 458 | 452 | } |
| 459 | 453 | |
| 460 | 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 | 456 | u32 requested, u32 audited, u32 denied, |
| 463 | 457 | struct common_audit_data *a, |
| 464 | 458 | unsigned flags) |
| 465 | 459 | { |
| 466 | 460 | struct common_audit_data stack_data; |
| 467 | − struct selinux_audit_data sad = {0,}; | |
| 468 | − struct selinux_late_audit_data slad; | |
| 461 | + struct selinux_audit_data sad; | |
| 469 | 462 | |
| 470 | 463 | if (!a) { |
| 471 | 464 | a = &stack_data; |
| 472 | − COMMON_AUDIT_DATA_INIT(a, NONE); | |
| 473 | − a->selinux_audit_data = &sad; | |
| 465 | + a->type = LSM_AUDIT_DATA_NONE; | |
| 474 | 466 | } |
| 475 | 467 | |
| 476 | 468 | /* |
| @@ -484,104 +476,34 @@ static noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass, · 7 unmodified lines | ||
| 484 | 476 | (flags & MAY_NOT_BLOCK)) |
| 485 | 477 | return -ECHILD; |
| 486 | 478 | |
| 487 | − slad.tclass = tclass; | |
| 488 | − slad.requested = requested; | |
| 489 | − slad.ssid = ssid; | |
| 490 | − slad.tsid = tsid; | |
| 491 | − slad.audited = audited; | |
| 492 | − slad.denied = denied; | |
| 479 | + sad.tclass = tclass; | |
| 480 | + sad.requested = requested; | |
| 481 | + sad.ssid = ssid; | |
| 482 | + sad.tsid = tsid; | |
| 483 | + sad.audited = audited; | |
| 484 | + sad.denied = denied; | |
| 485 | + | |
| 486 | + a->selinux_audit_data = &sad; | |
| 493 | 487 | |
| 494 | − a->selinux_audit_data->slad = &slad; | |
| 495 | 488 | common_lsm_audit(a, avc_audit_pre_callback, avc_audit_post_callback); |
| 496 | 489 | return 0; |
| 497 | 490 | } |
| 498 | 491 | |
| 499 | −/** | |
| 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 | 492 | /** |
| 561 | 493 | * avc_add_callback - Register a callback for security events. |
| 562 | 494 | * @callback: callback function |
| 563 | 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 | |
| 570 | − * related to the SID pair (@ssid, @tsid) | |
| 571 | − * and the permissions @perms, interpreting | |
| 572 | − * @perms based on @tclass. Returns %0 on success or | |
| 573 | − * -%ENOMEM if insufficient memory exists to add the callback. | |
| 497 | + * Register a callback function for events in the set @events. | |
| 498 | + * Returns %0 on success or -%ENOMEM if insufficient memory | |
| 499 | + * exists to add the callback. | |
| 574 | 500 | */ |
| 575 | −int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid, | |
| 576 | − u16 tclass, u32 perms, | |
| 577 | − u32 *out_retained), | |
| 578 | − u32 events, u32 ssid, u32 tsid, | |
| 579 | − u16 tclass, u32 perms) | |
| 501 | +int __init avc_add_callback(int (*callback)(u32 event), u32 events) | |
| 580 | 502 | { |
| 581 | 503 | struct avc_callback_node *c; |
| 582 | 504 | int rc = 0; |
| 583 | 505 | |
| 584 | − c = kmalloc(sizeof(*c), GFP_ATOMIC); | |
| 506 | + c = kmalloc(sizeof(*c), GFP_KERNEL); | |
| 585 | 507 | if (!c) { |
| 586 | 508 | rc = -ENOMEM; |
| 587 | 509 | goto out; |
| @@ -589,9 +511,6 @@ int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid, · 1 unmodified line | ||
| 589 | 511 | |
| 590 | 512 | c->callback = callback; |
| 591 | 513 | c->events = events; |
| 592 | − c->ssid = ssid; | |
| 593 | − c->tsid = tsid; | |
| 594 | − c->perms = perms; | |
| 595 | 514 | c->next = avc_callbacks; |
| 596 | 515 | avc_callbacks = c; |
| 597 | 516 | out: |
| @@ -731,8 +650,7 @@ int avc_ss_reset(u32 seqno) · 133 unmodified lines | ||
| 731 | 650 | |
| 732 | 651 | for (c = avc_callbacks; c; c = c->next) { |
| 733 | 652 | if (c->events & AVC_CALLBACK_RESET) { |
| 734 | − tmprc = c->callback(AVC_CALLBACK_RESET, | |
| 735 | − 0, 0, 0, 0, NULL); | |
| 653 | + tmprc = c->callback(AVC_CALLBACK_RESET); | |
| 736 | 654 | /* save the first error encountered for the return |
| 737 | 655 | value and continue processing the callbacks */ |
| 738 | 656 | if (!rc) |
| @@ -1420,16 +1420,13 @@ static int cred_has_capability(const struct cred *cred, · 1419 unmodified lines | ||
| 1420 | 1420 | int cap, int audit) |
| 1421 | 1421 | { |
| 1422 | 1422 | struct common_audit_data ad; |
| 1423 | − struct selinux_audit_data sad = {0,}; | |
| 1424 | 1423 | struct av_decision avd; |
| 1425 | 1424 | u16 sclass; |
| 1426 | 1425 | u32 sid = cred_sid(cred); |
| 1427 | 1426 | u32 av = CAP_TO_MASK(cap); |
| 1428 | 1427 | int rc; |
| 1429 | 1428 | |
| 1430 | − COMMON_AUDIT_DATA_INIT(&ad, CAP); | |
| 1431 | − ad.selinux_audit_data = &sad; | |
| 1432 | − ad.tsk = current; | |
| 1429 | + ad.type = LSM_AUDIT_DATA_CAP; | |
| 1433 | 1430 | ad.u.cap = cap; |
| 1434 | 1431 | |
| 1435 | 1432 | switch (CAP_TO_INDEX(cap)) { |
| @@ -1488,20 +1485,6 @@ static int inode_has_perm(const struct cred *cred, · 52 unmodified lines | ||
| 1488 | 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 | 1488 | /* Same as inode_has_perm, but pass explicit audit data containing |
| 1506 | 1489 | the dentry to help the auditing code to more easily generate the |
| 1507 | 1490 | pathname if needed. */ |
| @@ -1511,11 +1494,9 @@ static inline int dentry_has_perm(const struct cred *cred, · 3 unmodified lines | ||
| 1511 | 1494 | { |
| 1512 | 1495 | struct inode *inode = dentry->d_inode; |
| 1513 | 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 | 1499 | ad.u.dentry = dentry; |
| 1518 | − ad.selinux_audit_data = &sad; | |
| 1519 | 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, · 6 unmodified lines | ||
| 1528 | 1509 | { |
| 1529 | 1510 | struct inode *inode = path->dentry->d_inode; |
| 1530 | 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 | 1514 | ad.u.path = *path; |
| 1535 | − ad.selinux_audit_data = &sad; | |
| 1536 | 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, · 12 unmodified lines | ||
| 1551 | 1530 | struct file_security_struct *fsec = file->f_security; |
| 1552 | 1531 | struct inode *inode = file->f_path.dentry->d_inode; |
| 1553 | 1532 | struct common_audit_data ad; |
| 1554 | − struct selinux_audit_data sad = {0,}; | |
| 1555 | 1533 | u32 sid = cred_sid(cred); |
| 1556 | 1534 | int rc; |
| 1557 | 1535 | |
| 1558 | − COMMON_AUDIT_DATA_INIT(&ad, PATH); | |
| 1536 | + ad.type = LSM_AUDIT_DATA_PATH; | |
| 1559 | 1537 | ad.u.path = file->f_path; |
| 1560 | − ad.selinux_audit_data = &sad; | |
| 1561 | 1538 | |
| 1562 | 1539 | if (sid != fsec->sid) { |
| 1563 | 1540 | rc = avc_has_perm(sid, fsec->sid, |
| @@ -1587,7 +1564,6 @@ static int may_create(struct inode *dir, · 23 unmodified lines | ||
| 1587 | 1564 | struct superblock_security_struct *sbsec; |
| 1588 | 1565 | u32 sid, newsid; |
| 1589 | 1566 | struct common_audit_data ad; |
| 1590 | − struct selinux_audit_data sad = {0,}; | |
| 1591 | 1567 | int rc; |
| 1592 | 1568 | |
| 1593 | 1569 | dsec = dir->i_security; |
| @@ -1596,9 +1572,8 @@ static int may_create(struct inode *dir, · 2 unmodified lines | ||
| 1596 | 1572 | sid = tsec->sid; |
| 1597 | 1573 | newsid = tsec->create_sid; |
| 1598 | 1574 | |
| 1599 | − COMMON_AUDIT_DATA_INIT(&ad, DENTRY); | |
| 1575 | + ad.type = LSM_AUDIT_DATA_DENTRY; | |
| 1600 | 1576 | ad.u.dentry = dentry; |
| 1601 | − ad.selinux_audit_data = &sad; | |
| 1602 | 1577 | |
| 1603 | 1578 | rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, |
| 1604 | 1579 | DIR__ADD_NAME | DIR__SEARCH, |
| @@ -1643,7 +1618,6 @@ static int may_link(struct inode *dir, · 38 unmodified lines | ||
| 1643 | 1618 | { |
| 1644 | 1619 | struct inode_security_struct *dsec, *isec; |
| 1645 | 1620 | struct common_audit_data ad; |
| 1646 | − struct selinux_audit_data sad = {0,}; | |
| 1647 | 1621 | u32 sid = current_sid(); |
| 1648 | 1622 | u32 av; |
| 1649 | 1623 | int rc; |
| @@ -1651,9 +1625,8 @@ static int may_link(struct inode *dir, · 1 unmodified line | ||
| 1651 | 1625 | dsec = dir->i_security; |
| 1652 | 1626 | isec = dentry->d_inode->i_security; |
| 1653 | 1627 | |
| 1654 | − COMMON_AUDIT_DATA_INIT(&ad, DENTRY); | |
| 1628 | + ad.type = LSM_AUDIT_DATA_DENTRY; | |
| 1655 | 1629 | ad.u.dentry = dentry; |
| 1656 | − ad.selinux_audit_data = &sad; | |
| 1657 | 1630 | |
| 1658 | 1631 | av = DIR__SEARCH; |
| 1659 | 1632 | av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME); |
| @@ -1688,7 +1661,6 @@ static inline int may_rename(struct inode *old_dir, · 28 unmodified lines | ||
| 1688 | 1661 | { |
| 1689 | 1662 | struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec; |
| 1690 | 1663 | struct common_audit_data ad; |
| 1691 | − struct selinux_audit_data sad = {0,}; | |
| 1692 | 1664 | u32 sid = current_sid(); |
| 1693 | 1665 | u32 av; |
| 1694 | 1666 | int old_is_dir, new_is_dir; |
| @@ -1699,8 +1671,7 @@ static inline int may_rename(struct inode *old_dir, · 4 unmodified lines | ||
| 1699 | 1671 | old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode); |
| 1700 | 1672 | new_dsec = new_dir->i_security; |
| 1701 | 1673 | |
| 1702 | − COMMON_AUDIT_DATA_INIT(&ad, DENTRY); | |
| 1703 | − ad.selinux_audit_data = &sad; | |
| 1674 | + ad.type = LSM_AUDIT_DATA_DENTRY; | |
| 1704 | 1675 | |
| 1705 | 1676 | ad.u.dentry = old_dentry; |
| 1706 | 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) · 279 unmodified lines | ||
| 1986 | 1957 | struct task_security_struct *new_tsec; |
| 1987 | 1958 | struct inode_security_struct *isec; |
| 1988 | 1959 | struct common_audit_data ad; |
| 1989 | − struct selinux_audit_data sad = {0,}; | |
| 1990 | 1960 | struct inode *inode = bprm->file->f_path.dentry->d_inode; |
| 1991 | 1961 | int rc; |
| 1992 | 1962 | |
| @@ -2032,8 +2002,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) · 39 unmodified lines | ||
| 2032 | 2002 | return rc; |
| 2033 | 2003 | } |
| 2034 | 2004 | |
| 2035 | − COMMON_AUDIT_DATA_INIT(&ad, PATH); | |
| 2036 | − ad.selinux_audit_data = &sad; | |
| 2005 | + ad.type = LSM_AUDIT_DATA_PATH; | |
| 2037 | 2006 | ad.u.path = bprm->file->f_path; |
| 2038 | 2007 | |
| 2039 | 2008 | if ((bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) || |
| @@ -2123,8 +2092,6 @@ static int selinux_bprm_secureexec(struct linux_binprm *bprm) · 83 unmodified lines | ||
| 2123 | 2092 | static inline void flush_unauthorized_files(const struct cred *cred, |
| 2124 | 2093 | struct files_struct *files) |
| 2125 | 2094 | { |
| 2126 | − struct common_audit_data ad; | |
| 2127 | − struct selinux_audit_data sad = {0,}; | |
| 2128 | 2095 | struct file *file, *devnull = NULL; |
| 2129 | 2096 | struct tty_struct *tty; |
| 2130 | 2097 | struct fdtable *fdt; |
| @@ -2136,21 +2103,17 @@ static inline void flush_unauthorized_files(const struct cred *cred, · 5 unmodified lines | ||
| 2136 | 2103 | spin_lock(&tty_files_lock); |
| 2137 | 2104 | if (!list_empty(&tty->tty_files)) { |
| 2138 | 2105 | struct tty_file_private *file_priv; |
| 2139 | − struct inode *inode; | |
| 2140 | 2106 | |
| 2141 | 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 | 2109 | than using file_has_perm, as this particular open |
| 2144 | 2110 | file may belong to another process and we are only |
| 2145 | 2111 | interested in the inode-based check here. */ |
| 2146 | 2112 | file_priv = list_first_entry(&tty->tty_files, |
| 2147 | 2113 | struct tty_file_private, list); |
| 2148 | 2114 | file = file_priv->file; |
| 2149 | − inode = file->f_path.dentry->d_inode; | |
| 2150 | − if (inode_has_perm_noadp(cred, inode, | |
| 2151 | − FILE__READ | FILE__WRITE, 0)) { | |
| 2115 | + if (path_has_perm(cred, &file->f_path, FILE__READ | FILE__WRITE)) | |
| 2152 | 2116 | drop_tty = 1; |
| 2153 | − } | |
| 2154 | 2117 | } |
| 2155 | 2118 | spin_unlock(&tty_files_lock); |
| 2156 | 2119 | tty_kref_put(tty); |
| @@ -2160,10 +2123,6 @@ static inline void flush_unauthorized_files(const struct cred *cred, · 3 unmodified lines | ||
| 2160 | 2123 | no_tty(); |
| 2161 | 2124 | |
| 2162 | 2125 | /* Revalidate access to inherited open files. */ |
| 2163 | − | |
| 2164 | − COMMON_AUDIT_DATA_INIT(&ad, INODE); | |
| 2165 | − ad.selinux_audit_data = &sad; | |
| 2166 | − | |
| 2167 | 2126 | spin_lock(&files->file_lock); |
| 2168 | 2127 | for (;;) { |
| 2169 | 2128 | unsigned long set, i; |
| @@ -2500,7 +2459,6 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) · 330 unmodified lines | ||
| 2500 | 2459 | { |
| 2501 | 2460 | const struct cred *cred = current_cred(); |
| 2502 | 2461 | struct common_audit_data ad; |
| 2503 | − struct selinux_audit_data sad = {0,}; | |
| 2504 | 2462 | int rc; |
| 2505 | 2463 | |
| 2506 | 2464 | rc = superblock_doinit(sb, data); |
| @@ -2511,8 +2469,7 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) · 4 unmodified lines | ||
| 2511 | 2469 | if (flags & MS_KERNMOUNT) |
| 2512 | 2470 | return 0; |
| 2513 | 2471 | |
| 2514 | − COMMON_AUDIT_DATA_INIT(&ad, DENTRY); | |
| 2515 | − ad.selinux_audit_data = &sad; | |
| 2472 | + ad.type = LSM_AUDIT_DATA_DENTRY; | |
| 2516 | 2473 | ad.u.dentry = sb->s_root; |
| 2517 | 2474 | return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad); |
| 2518 | 2475 | } |
| @@ -2521,10 +2478,8 @@ static int selinux_sb_statfs(struct dentry *dentry) · 2 unmodified lines | ||
| 2521 | 2478 | { |
| 2522 | 2479 | const struct cred *cred = current_cred(); |
| 2523 | 2480 | struct common_audit_data ad; |
| 2524 | − struct selinux_audit_data sad = {0,}; | |
| 2525 | 2481 | |
| 2526 | − COMMON_AUDIT_DATA_INIT(&ad, DENTRY); | |
| 2527 | − ad.selinux_audit_data = &sad; | |
| 2482 | + ad.type = LSM_AUDIT_DATA_DENTRY; | |
| 2528 | 2483 | ad.u.dentry = dentry->d_sb->s_root; |
| 2529 | 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 · 153 unmodified lines | ||
| 2684 | 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 | 2660 | static int selinux_inode_permission(struct inode *inode, int mask) |
| 2688 | 2661 | { |
| 2689 | 2662 | const struct cred *cred = current_cred(); |
| 2690 | − struct common_audit_data ad; | |
| 2691 | − struct selinux_audit_data sad = {0,}; | |
| 2692 | 2663 | u32 perms; |
| 2693 | 2664 | bool from_access; |
| 2694 | 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 | 2672 | from_access = mask & MAY_ACCESS; |
| 2697 | 2673 | mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND); |
| @@ -2700,22 +2676,34 @@ static int selinux_inode_permission(struct inode *inode, int mask) · 2 unmodified lines | ||
| 2700 | 2676 | if (!mask) |
| 2701 | 2677 | return 0; |
| 2702 | 2678 | |
| 2703 | − COMMON_AUDIT_DATA_INIT(&ad, INODE); | |
| 2704 | − ad.selinux_audit_data = &sad; | |
| 2705 | − ad.u.inode = inode; | |
| 2679 | + validate_creds(cred); | |
| 2706 | 2680 | |
| 2707 | − if (from_access) | |
| 2708 | − ad.selinux_audit_data->auditdeny |= FILE__AUDIT_ACCESS; | |
| 2681 | + if (unlikely(IS_PRIVATE(inode))) | |
| 2682 | + return 0; | |
| 2709 | 2683 | |
| 2710 | 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 | 2702 | static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) |
| 2716 | 2703 | { |
| 2717 | 2704 | const struct cred *cred = current_cred(); |
| 2718 | 2705 | unsigned int ia_valid = iattr->ia_valid; |
| 2706 | + __u32 av = FILE__WRITE; | |
| 2719 | 2707 | |
| 2720 | 2708 | /* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */ |
| 2721 | 2709 | if (ia_valid & ATTR_FORCE) { |
| @@ -2729,7 +2717,10 @@ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) · 7 unmodified lines | ||
| 2729 | 2717 | ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET)) |
| 2730 | 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 | 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, · 35 unmodified lines | ||
| 2771 | 2762 | struct inode_security_struct *isec = inode->i_security; |
| 2772 | 2763 | struct superblock_security_struct *sbsec; |
| 2773 | 2764 | struct common_audit_data ad; |
| 2774 | − struct selinux_audit_data sad = {0,}; | |
| 2775 | 2765 | u32 newsid, sid = current_sid(); |
| 2776 | 2766 | int rc = 0; |
| 2777 | 2767 | |
| @@ -2785,8 +2775,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, · 7 unmodified lines | ||
| 2785 | 2775 | if (!inode_owner_or_capable(inode)) |
| 2786 | 2776 | return -EPERM; |
| 2787 | 2777 | |
| 2788 | − COMMON_AUDIT_DATA_INIT(&ad, DENTRY); | |
| 2789 | − ad.selinux_audit_data = &sad; | |
| 2778 | + ad.type = LSM_AUDIT_DATA_DENTRY; | |
| 2790 | 2779 | ad.u.dentry = dentry; |
| 2791 | 2780 | |
| 2792 | 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, · 3 unmodified lines | ||
| 2796 | 2785 | |
| 2797 | 2786 | rc = security_context_to_sid(value, size, &newsid); |
| 2798 | 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 | 2805 | return rc; |
| 2806 | + } | |
| 2801 | 2807 | rc = security_context_to_sid_force(value, size, &newsid); |
| 2802 | 2808 | } |
| 2803 | 2809 | if (rc) |
| @@ -2977,7 +2983,7 @@ static int selinux_file_permission(struct file *file, int mask) · 173 unmodified lines | ||
| 2977 | 2983 | |
| 2978 | 2984 | if (sid == fsec->sid && fsec->isid == isec->sid && |
| 2979 | 2985 | fsec->pseqno == avc_policy_seqno()) |
| 2980 | − /* No change since dentry_open check. */ | |
| 2986 | + /* No change since file_open check. */ | |
| 2981 | 2987 | return 0; |
| 2982 | 2988 | |
| 2983 | 2989 | return selinux_revalidate_file_permission(file, mask); |
| @@ -3236,15 +3242,13 @@ static int selinux_file_receive(struct file *file) · 252 unmodified lines | ||
| 3236 | 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 | 3247 | struct file_security_struct *fsec; |
| 3242 | − struct inode *inode; | |
| 3243 | 3248 | struct inode_security_struct *isec; |
| 3244 | 3249 | |
| 3245 | − inode = file->f_path.dentry->d_inode; | |
| 3246 | 3250 | fsec = file->f_security; |
| 3247 | − isec = inode->i_security; | |
| 3251 | + isec = file->f_path.dentry->d_inode->i_security; | |
| 3248 | 3252 | /* |
| 3249 | 3253 | * Save inode label and policy sequence number |
| 3250 | 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) · 11 unmodified lines | ||
| 3262 | 3266 | * new inode label or new policy. |
| 3263 | 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 | 3272 | /* task security operations */ |
| @@ -3381,12 +3385,10 @@ static int selinux_kernel_module_request(char *kmod_name) · 112 unmodified lines | ||
| 3381 | 3385 | { |
| 3382 | 3386 | u32 sid; |
| 3383 | 3387 | struct common_audit_data ad; |
| 3384 | − struct selinux_audit_data sad = {0,}; | |
| 3385 | 3388 | |
| 3386 | 3389 | sid = task_sid(current); |
| 3387 | 3390 | |
| 3388 | − COMMON_AUDIT_DATA_INIT(&ad, KMOD); | |
| 3389 | − ad.selinux_audit_data = &sad; | |
| 3391 | + ad.type = LSM_AUDIT_DATA_KMOD; | |
| 3390 | 3392 | ad.u.kmod_name = kmod_name; |
| 3391 | 3393 | |
| 3392 | 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) · 366 unmodified lines | ||
| 3759 | 3761 | { |
| 3760 | 3762 | struct sk_security_struct *sksec = sk->sk_security; |
| 3761 | 3763 | struct common_audit_data ad; |
| 3762 | − struct selinux_audit_data sad = {0,}; | |
| 3763 | 3764 | struct lsm_network_audit net = {0,}; |
| 3764 | 3765 | u32 tsid = task_sid(task); |
| 3765 | 3766 | |
| 3766 | 3767 | if (sksec->sid == SECINITSID_KERNEL) |
| 3767 | 3768 | return 0; |
| 3768 | 3769 | |
| 3769 | − COMMON_AUDIT_DATA_INIT(&ad, NET); | |
| 3770 | − ad.selinux_audit_data = &sad; | |
| 3770 | + ad.type = LSM_AUDIT_DATA_NET; | |
| 3771 | 3771 | ad.u.net = &net; |
| 3772 | 3772 | ad.u.net->sk = sk; |
| 3773 | 3773 | |
| @@ -3847,7 +3847,6 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in · 73 unmodified lines | ||
| 3847 | 3847 | char *addrp; |
| 3848 | 3848 | struct sk_security_struct *sksec = sk->sk_security; |
| 3849 | 3849 | struct common_audit_data ad; |
| 3850 | − struct selinux_audit_data sad = {0,}; | |
| 3851 | 3850 | struct lsm_network_audit net = {0,}; |
| 3852 | 3851 | struct sockaddr_in *addr4 = NULL; |
| 3853 | 3852 | struct sockaddr_in6 *addr6 = NULL; |
| @@ -3874,8 +3873,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in · 20 unmodified lines | ||
| 3874 | 3873 | snum, &sid); |
| 3875 | 3874 | if (err) |
| 3876 | 3875 | goto out; |
| 3877 | − COMMON_AUDIT_DATA_INIT(&ad, NET); | |
| 3878 | − ad.selinux_audit_data = &sad; | |
| 3876 | + ad.type = LSM_AUDIT_DATA_NET; | |
| 3879 | 3877 | ad.u.net = &net; |
| 3880 | 3878 | ad.u.net->sport = htons(snum); |
| 3881 | 3879 | ad.u.net->family = family; |
| @@ -3909,8 +3907,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in · 27 unmodified lines | ||
| 3909 | 3907 | if (err) |
| 3910 | 3908 | goto out; |
| 3911 | 3909 | |
| 3912 | − COMMON_AUDIT_DATA_INIT(&ad, NET); | |
| 3913 | − ad.selinux_audit_data = &sad; | |
| 3910 | + ad.type = LSM_AUDIT_DATA_NET; | |
| 3914 | 3911 | ad.u.net = &net; |
| 3915 | 3912 | ad.u.net->sport = htons(snum); |
| 3916 | 3913 | ad.u.net->family = family; |
| @@ -3945,7 +3942,6 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, · 28 unmodified lines | ||
| 3945 | 3942 | if (sksec->sclass == SECCLASS_TCP_SOCKET || |
| 3946 | 3943 | sksec->sclass == SECCLASS_DCCP_SOCKET) { |
| 3947 | 3944 | struct common_audit_data ad; |
| 3948 | − struct selinux_audit_data sad = {0,}; | |
| 3949 | 3945 | struct lsm_network_audit net = {0,}; |
| 3950 | 3946 | struct sockaddr_in *addr4 = NULL; |
| 3951 | 3947 | struct sockaddr_in6 *addr6 = NULL; |
| @@ -3971,8 +3967,7 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, · 19 unmodified lines | ||
| 3971 | 3967 | perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ? |
| 3972 | 3968 | TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT; |
| 3973 | 3969 | |
| 3974 | − COMMON_AUDIT_DATA_INIT(&ad, NET); | |
| 3975 | − ad.selinux_audit_data = &sad; | |
| 3970 | + ad.type = LSM_AUDIT_DATA_NET; | |
| 3976 | 3971 | ad.u.net = &net; |
| 3977 | 3972 | ad.u.net->dport = htons(snum); |
| 3978 | 3973 | ad.u.net->family = sk->sk_family; |
| @@ -4064,12 +4059,10 @@ static int selinux_socket_unix_stream_connect(struct sock *sock, · 85 unmodified lines | ||
| 4064 | 4059 | struct sk_security_struct *sksec_other = other->sk_security; |
| 4065 | 4060 | struct sk_security_struct *sksec_new = newsk->sk_security; |
| 4066 | 4061 | struct common_audit_data ad; |
| 4067 | − struct selinux_audit_data sad = {0,}; | |
| 4068 | 4062 | struct lsm_network_audit net = {0,}; |
| 4069 | 4063 | int err; |
| 4070 | 4064 | |
| 4071 | − COMMON_AUDIT_DATA_INIT(&ad, NET); | |
| 4072 | − ad.selinux_audit_data = &sad; | |
| 4065 | + ad.type = LSM_AUDIT_DATA_NET; | |
| 4073 | 4066 | ad.u.net = &net; |
| 4074 | 4067 | ad.u.net->sk = other; |
| 4075 | 4068 | |
| @@ -4098,11 +4091,9 @@ static int selinux_socket_unix_may_send(struct socket *sock, · 22 unmodified lines | ||
| 4098 | 4091 | struct sk_security_struct *ssec = sock->sk->sk_security; |
| 4099 | 4092 | struct sk_security_struct *osec = other->sk->sk_security; |
| 4100 | 4093 | struct common_audit_data ad; |
| 4101 | − struct selinux_audit_data sad = {0,}; | |
| 4102 | 4094 | struct lsm_network_audit net = {0,}; |
| 4103 | 4095 | |
| 4104 | − COMMON_AUDIT_DATA_INIT(&ad, NET); | |
| 4105 | − ad.selinux_audit_data = &sad; | |
| 4096 | + ad.type = LSM_AUDIT_DATA_NET; | |
| 4106 | 4097 | ad.u.net = &net; |
| 4107 | 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, · 31 unmodified lines | ||
| 4140 | 4131 | struct sk_security_struct *sksec = sk->sk_security; |
| 4141 | 4132 | u32 sk_sid = sksec->sid; |
| 4142 | 4133 | struct common_audit_data ad; |
| 4143 | − struct selinux_audit_data sad = {0,}; | |
| 4144 | 4134 | struct lsm_network_audit net = {0,}; |
| 4145 | 4135 | char *addrp; |
| 4146 | 4136 | |
| 4147 | − COMMON_AUDIT_DATA_INIT(&ad, NET); | |
| 4148 | − ad.selinux_audit_data = &sad; | |
| 4137 | + ad.type = LSM_AUDIT_DATA_NET; | |
| 4149 | 4138 | ad.u.net = &net; |
| 4150 | 4139 | ad.u.net->netif = skb->skb_iif; |
| 4151 | 4140 | ad.u.net->family = family; |
| @@ -4175,7 +4164,6 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) · 23 unmodified lines | ||
| 4175 | 4164 | u16 family = sk->sk_family; |
| 4176 | 4165 | u32 sk_sid = sksec->sid; |
| 4177 | 4166 | struct common_audit_data ad; |
| 4178 | − struct selinux_audit_data sad = {0,}; | |
| 4179 | 4167 | struct lsm_network_audit net = {0,}; |
| 4180 | 4168 | char *addrp; |
| 4181 | 4169 | u8 secmark_active; |
| @@ -4200,8 +4188,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) · 18 unmodified lines | ||
| 4200 | 4188 | if (!secmark_active && !peerlbl_active) |
| 4201 | 4189 | return 0; |
| 4202 | 4190 | |
| 4203 | − COMMON_AUDIT_DATA_INIT(&ad, NET); | |
| 4204 | − ad.selinux_audit_data = &sad; | |
| 4191 | + ad.type = LSM_AUDIT_DATA_NET; | |
| 4205 | 4192 | ad.u.net = &net; |
| 4206 | 4193 | ad.u.net->netif = skb->skb_iif; |
| 4207 | 4194 | ad.u.net->family = family; |
| @@ -4539,7 +4526,6 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, · 331 unmodified lines | ||
| 4539 | 4526 | char *addrp; |
| 4540 | 4527 | u32 peer_sid; |
| 4541 | 4528 | struct common_audit_data ad; |
| 4542 | − struct selinux_audit_data sad = {0,}; | |
| 4543 | 4529 | struct lsm_network_audit net = {0,}; |
| 4544 | 4530 | u8 secmark_active; |
| 4545 | 4531 | u8 netlbl_active; |
| @@ -4557,8 +4543,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, · 11 unmodified lines | ||
| 4557 | 4543 | if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0) |
| 4558 | 4544 | return NF_DROP; |
| 4559 | 4545 | |
| 4560 | − COMMON_AUDIT_DATA_INIT(&ad, NET); | |
| 4561 | − ad.selinux_audit_data = &sad; | |
| 4546 | + ad.type = LSM_AUDIT_DATA_NET; | |
| 4562 | 4547 | ad.u.net = &net; |
| 4563 | 4548 | ad.u.net->netif = ifindex; |
| 4564 | 4549 | ad.u.net->family = family; |
| @@ -4648,7 +4633,6 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, · 83 unmodified lines | ||
| 4648 | 4633 | struct sock *sk = skb->sk; |
| 4649 | 4634 | struct sk_security_struct *sksec; |
| 4650 | 4635 | struct common_audit_data ad; |
| 4651 | − struct selinux_audit_data sad = {0,}; | |
| 4652 | 4636 | struct lsm_network_audit net = {0,}; |
| 4653 | 4637 | char *addrp; |
| 4654 | 4638 | u8 proto; |
| @@ -4657,8 +4641,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, · 2 unmodified lines | ||
| 4657 | 4641 | return NF_ACCEPT; |
| 4658 | 4642 | sksec = sk->sk_security; |
| 4659 | 4643 | |
| 4660 | − COMMON_AUDIT_DATA_INIT(&ad, NET); | |
| 4661 | − ad.selinux_audit_data = &sad; | |
| 4644 | + ad.type = LSM_AUDIT_DATA_NET; | |
| 4662 | 4645 | ad.u.net = &net; |
| 4663 | 4646 | ad.u.net->netif = ifindex; |
| 4664 | 4647 | ad.u.net->family = family; |
| @@ -4683,7 +4666,6 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, · 18 unmodified lines | ||
| 4683 | 4666 | u32 peer_sid; |
| 4684 | 4667 | struct sock *sk; |
| 4685 | 4668 | struct common_audit_data ad; |
| 4686 | − struct selinux_audit_data sad = {0,}; | |
| 4687 | 4669 | struct lsm_network_audit net = {0,}; |
| 4688 | 4670 | char *addrp; |
| 4689 | 4671 | u8 secmark_active; |
| @@ -4730,8 +4712,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, · 40 unmodified lines | ||
| 4730 | 4712 | secmark_perm = PACKET__SEND; |
| 4731 | 4713 | } |
| 4732 | 4714 | |
| 4733 | − COMMON_AUDIT_DATA_INIT(&ad, NET); | |
| 4734 | − ad.selinux_audit_data = &sad; | |
| 4715 | + ad.type = LSM_AUDIT_DATA_NET; | |
| 4735 | 4716 | ad.u.net = &net; |
| 4736 | 4717 | ad.u.net->netif = ifindex; |
| 4737 | 4718 | ad.u.net->family = family; |
| @@ -4849,13 +4830,11 @@ static int ipc_has_perm(struct kern_ipc_perm *ipc_perms, · 111 unmodified lines | ||
| 4849 | 4830 | { |
| 4850 | 4831 | struct ipc_security_struct *isec; |
| 4851 | 4832 | struct common_audit_data ad; |
| 4852 | − struct selinux_audit_data sad = {0,}; | |
| 4853 | 4833 | u32 sid = current_sid(); |
| 4854 | 4834 | |
| 4855 | 4835 | isec = ipc_perms->security; |
| 4856 | 4836 | |
| 4857 | − COMMON_AUDIT_DATA_INIT(&ad, IPC); | |
| 4858 | − ad.selinux_audit_data = &sad; | |
| 4837 | + ad.type = LSM_AUDIT_DATA_IPC; | |
| 4859 | 4838 | ad.u.ipc_id = ipc_perms->key; |
| 4860 | 4839 | |
| 4861 | 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) · 14 unmodified lines | ||
| 4876 | 4855 | { |
| 4877 | 4856 | struct ipc_security_struct *isec; |
| 4878 | 4857 | struct common_audit_data ad; |
| 4879 | − struct selinux_audit_data sad = {0,}; | |
| 4880 | 4858 | u32 sid = current_sid(); |
| 4881 | 4859 | int rc; |
| 4882 | 4860 | |
| @@ -4886,8 +4864,7 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq) · 3 unmodified lines | ||
| 4886 | 4864 | |
| 4887 | 4865 | isec = msq->q_perm.security; |
| 4888 | 4866 | |
| 4889 | − COMMON_AUDIT_DATA_INIT(&ad, IPC); | |
| 4890 | − ad.selinux_audit_data = &sad; | |
| 4867 | + ad.type = LSM_AUDIT_DATA_IPC; | |
| 4891 | 4868 | ad.u.ipc_id = msq->q_perm.key; |
| 4892 | 4869 | |
| 4893 | 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) · 14 unmodified lines | ||
| 4908 | 4885 | { |
| 4909 | 4886 | struct ipc_security_struct *isec; |
| 4910 | 4887 | struct common_audit_data ad; |
| 4911 | − struct selinux_audit_data sad = {0,}; | |
| 4912 | 4888 | u32 sid = current_sid(); |
| 4913 | 4889 | |
| 4914 | 4890 | isec = msq->q_perm.security; |
| 4915 | 4891 | |
| 4916 | − COMMON_AUDIT_DATA_INIT(&ad, IPC); | |
| 4917 | − ad.selinux_audit_data = &sad; | |
| 4892 | + ad.type = LSM_AUDIT_DATA_IPC; | |
| 4918 | 4893 | ad.u.ipc_id = msq->q_perm.key; |
| 4919 | 4894 | |
| 4920 | 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, · 33 unmodified lines | ||
| 4954 | 4929 | struct ipc_security_struct *isec; |
| 4955 | 4930 | struct msg_security_struct *msec; |
| 4956 | 4931 | struct common_audit_data ad; |
| 4957 | − struct selinux_audit_data sad = {0,}; | |
| 4958 | 4932 | u32 sid = current_sid(); |
| 4959 | 4933 | int rc; |
| 4960 | 4934 | |
| @@ -4975,8 +4949,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, · 14 unmodified lines | ||
| 4975 | 4949 | return rc; |
| 4976 | 4950 | } |
| 4977 | 4951 | |
| 4978 | − COMMON_AUDIT_DATA_INIT(&ad, IPC); | |
| 4979 | − ad.selinux_audit_data = &sad; | |
| 4952 | + ad.type = LSM_AUDIT_DATA_IPC; | |
| 4980 | 4953 | ad.u.ipc_id = msq->q_perm.key; |
| 4981 | 4954 | |
| 4982 | 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, · 18 unmodified lines | ||
| 5001 | 4974 | struct ipc_security_struct *isec; |
| 5002 | 4975 | struct msg_security_struct *msec; |
| 5003 | 4976 | struct common_audit_data ad; |
| 5004 | − struct selinux_audit_data sad = {0,}; | |
| 5005 | 4977 | u32 sid = task_sid(target); |
| 5006 | 4978 | int rc; |
| 5007 | 4979 | |
| 5008 | 4980 | isec = msq->q_perm.security; |
| 5009 | 4981 | msec = msg->security; |
| 5010 | 4982 | |
| 5011 | − COMMON_AUDIT_DATA_INIT(&ad, IPC); | |
| 5012 | − ad.selinux_audit_data = &sad; | |
| 4983 | + ad.type = LSM_AUDIT_DATA_IPC; | |
| 5013 | 4984 | ad.u.ipc_id = msq->q_perm.key; |
| 5014 | 4985 | |
| 5015 | 4986 | rc = avc_has_perm(sid, isec->sid, |
| @@ -5025,7 +4996,6 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp) · 9 unmodified lines | ||
| 5025 | 4996 | { |
| 5026 | 4997 | struct ipc_security_struct *isec; |
| 5027 | 4998 | struct common_audit_data ad; |
| 5028 | − struct selinux_audit_data sad = {0,}; | |
| 5029 | 4999 | u32 sid = current_sid(); |
| 5030 | 5000 | int rc; |
| 5031 | 5001 | |
| @@ -5035,8 +5005,7 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp) · 3 unmodified lines | ||
| 5035 | 5005 | |
| 5036 | 5006 | isec = shp->shm_perm.security; |
| 5037 | 5007 | |
| 5038 | − COMMON_AUDIT_DATA_INIT(&ad, IPC); | |
| 5039 | − ad.selinux_audit_data = &sad; | |
| 5008 | + ad.type = LSM_AUDIT_DATA_IPC; | |
| 5040 | 5009 | ad.u.ipc_id = shp->shm_perm.key; |
| 5041 | 5010 | |
| 5042 | 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) · 14 unmodified lines | ||
| 5057 | 5026 | { |
| 5058 | 5027 | struct ipc_security_struct *isec; |
| 5059 | 5028 | struct common_audit_data ad; |
| 5060 | − struct selinux_audit_data sad = {0,}; | |
| 5061 | 5029 | u32 sid = current_sid(); |
| 5062 | 5030 | |
| 5063 | 5031 | isec = shp->shm_perm.security; |
| 5064 | 5032 | |
| 5065 | − COMMON_AUDIT_DATA_INIT(&ad, IPC); | |
| 5066 | − ad.selinux_audit_data = &sad; | |
| 5033 | + ad.type = LSM_AUDIT_DATA_IPC; | |
| 5067 | 5034 | ad.u.ipc_id = shp->shm_perm.key; |
| 5068 | 5035 | |
| 5069 | 5036 | return avc_has_perm(sid, isec->sid, SECCLASS_SHM, |
| @@ -5121,7 +5088,6 @@ static int selinux_sem_alloc_security(struct sem_array *sma) · 51 unmodified lines | ||
| 5121 | 5088 | { |
| 5122 | 5089 | struct ipc_security_struct *isec; |
| 5123 | 5090 | struct common_audit_data ad; |
| 5124 | − struct selinux_audit_data sad = {0,}; | |
| 5125 | 5091 | u32 sid = current_sid(); |
| 5126 | 5092 | int rc; |
| 5127 | 5093 | |
| @@ -5131,8 +5097,7 @@ static int selinux_sem_alloc_security(struct sem_array *sma) · 3 unmodified lines | ||
| 5131 | 5097 | |
| 5132 | 5098 | isec = sma->sem_perm.security; |
| 5133 | 5099 | |
| 5134 | − COMMON_AUDIT_DATA_INIT(&ad, IPC); | |
| 5135 | − ad.selinux_audit_data = &sad; | |
| 5100 | + ad.type = LSM_AUDIT_DATA_IPC; | |
| 5136 | 5101 | ad.u.ipc_id = sma->sem_perm.key; |
| 5137 | 5102 | |
| 5138 | 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) · 14 unmodified lines | ||
| 5153 | 5118 | { |
| 5154 | 5119 | struct ipc_security_struct *isec; |
| 5155 | 5120 | struct common_audit_data ad; |
| 5156 | − struct selinux_audit_data sad = {0,}; | |
| 5157 | 5121 | u32 sid = current_sid(); |
| 5158 | 5122 | |
| 5159 | 5123 | isec = sma->sem_perm.security; |
| 5160 | 5124 | |
| 5161 | − COMMON_AUDIT_DATA_INIT(&ad, IPC); | |
| 5162 | − ad.selinux_audit_data = &sad; | |
| 5125 | + ad.type = LSM_AUDIT_DATA_IPC; | |
| 5163 | 5126 | ad.u.ipc_id = sma->sem_perm.key; |
| 5164 | 5127 | |
| 5165 | 5128 | return avc_has_perm(sid, isec->sid, SECCLASS_SEM, |
| @@ -5339,8 +5302,23 @@ static int selinux_setprocattr(struct task_struct *p, · 173 unmodified lines | ||
| 5339 | 5302 | } |
| 5340 | 5303 | error = security_context_to_sid(value, size, &sid); |
| 5341 | 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 | 5320 | return error; |
| 5321 | + } | |
| 5344 | 5322 | error = security_context_to_sid_force(value, size, |
| 5345 | 5323 | &sid); |
| 5346 | 5324 | } |
| @@ -5600,7 +5578,7 @@ static struct security_operations selinux_ops = { · 253 unmodified lines | ||
| 5600 | 5578 | .file_send_sigiotask = selinux_file_send_sigiotask, |
| 5601 | 5579 | .file_receive = selinux_file_receive, |
| 5602 | 5580 | |
| 5603 | − .dentry_open = selinux_dentry_open, | |
| 5581 | + .file_open = selinux_file_open, | |
| 5604 | 5582 | |
| 5605 | 5583 | .task_create = selinux_task_create, |
| 5606 | 5584 | .cred_alloc_blank = selinux_cred_alloc_blank, |
| @@ -49,7 +49,7 @@ struct avc_cache_stats { · 48 unmodified lines | ||
| 49 | 49 | /* |
| 50 | 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 | 53 | u32 ssid; |
| 54 | 54 | u32 tsid; |
| 55 | 55 | u16 tclass; |
| @@ -59,29 +59,87 @@ struct selinux_late_audit_data { · 3 unmodified lines | ||
| 59 | 59 | int result; |
| 60 | 60 | }; |
| 61 | 61 | |
| 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 | 62 | /* |
| 75 | 63 | * AVC operations |
| 76 | 64 | */ |
| 77 | 65 | |
| 78 | 66 | void __init avc_init(void); |
| 79 | 67 | |
| 80 | −int avc_audit(u32 ssid, u32 tsid, | |
| 81 | − u16 tclass, u32 requested, | |
| 82 | − struct av_decision *avd, | |
| 83 | − int result, | |
| 84 | − struct common_audit_data *a, unsigned flags); | |
| 68 | +static inline u32 avc_audit_required(u32 requested, | |
| 69 | + struct av_decision *avd, | |
| 70 | + int result, | |
| 71 | + u32 auditdeny, | |
| 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 | 144 | #define AVC_STRICT 1 /* Ignore permissive mode. */ |
| 87 | 145 | int avc_has_perm_noaudit(u32 ssid, u32 tsid, |
| @@ -112,11 +170,7 @@ u32 avc_policy_seqno(void); · 24 unmodified lines | ||
| 112 | 170 | #define AVC_CALLBACK_AUDITDENY_ENABLE 64 |
| 113 | 171 | #define AVC_CALLBACK_AUDITDENY_DISABLE 128 |
| 114 | 172 | |
| 115 | −int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid, | |
| 116 | − u16 tclass, u32 perms, | |
| 117 | − u32 *out_retained), | |
| 118 | − u32 events, u32 ssid, u32 tsid, | |
| 119 | − u16 tclass, u32 perms); | |
| 173 | +int avc_add_callback(int (*callback)(u32 event), u32 events); | |
| 120 | 174 | |
| 121 | 175 | /* Exported to selinuxfs */ |
| 122 | 176 | int avc_get_hash_stats(char *page); |
| @@ -31,13 +31,15 @@ · 30 unmodified lines | ||
| 31 | 31 | #define POLICYDB_VERSION_BOUNDARY 24 |
| 32 | 32 | #define POLICYDB_VERSION_FILENAME_TRANS 25 |
| 33 | 33 | #define POLICYDB_VERSION_ROLETRANS 26 |
| 34 | +#define POLICYDB_VERSION_NEW_OBJECT_DEFAULTS 27 | |
| 35 | +#define POLICYDB_VERSION_DEFAULT_TYPE 28 | |
| 34 | 36 | |
| 35 | 37 | /* Range of policy versions we understand*/ |
| 36 | 38 | #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE |
| 37 | 39 | #ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX |
| 38 | 40 | #define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE |
| 39 | 41 | #else |
| 40 | −#define POLICYDB_VERSION_MAX POLICYDB_VERSION_ROLETRANS | |
| 42 | +#define POLICYDB_VERSION_MAX POLICYDB_VERSION_DEFAULT_TYPE | |
| 41 | 43 | #endif |
| 42 | 44 | |
| 43 | 45 | /* Mask for just the mount related flags */ |
| @@ -252,8 +252,7 @@ static void sel_netif_flush(void) · 251 unmodified lines | ||
| 252 | 252 | spin_unlock_bh(&sel_netif_lock); |
| 253 | 253 | } |
| 254 | 254 | |
| 255 | −static int sel_netif_avc_callback(u32 event, u32 ssid, u32 tsid, | |
| 256 | − u16 class, u32 perms, u32 *retained) | |
| 255 | +static int sel_netif_avc_callback(u32 event) | |
| 257 | 256 | { |
| 258 | 257 | if (event == AVC_CALLBACK_RESET) { |
| 259 | 258 | sel_netif_flush(); |
| @@ -292,8 +291,7 @@ static __init int sel_netif_init(void) · 32 unmodified lines | ||
| 292 | 291 | |
| 293 | 292 | register_netdevice_notifier(&sel_netif_netdev_notifier); |
| 294 | 293 | |
| 295 | − err = avc_add_callback(sel_netif_avc_callback, AVC_CALLBACK_RESET, | |
| 296 | − SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0); | |
| 294 | + err = avc_add_callback(sel_netif_avc_callback, AVC_CALLBACK_RESET); | |
| 297 | 295 | if (err) |
| 298 | 296 | panic("avc_add_callback() failed, error %d\n", err); |
| 299 | 297 | |
| @@ -297,8 +297,7 @@ static void sel_netnode_flush(void) · 296 unmodified lines | ||
| 297 | 297 | spin_unlock_bh(&sel_netnode_lock); |
| 298 | 298 | } |
| 299 | 299 | |
| 300 | −static int sel_netnode_avc_callback(u32 event, u32 ssid, u32 tsid, | |
| 301 | − u16 class, u32 perms, u32 *retained) | |
| 300 | +static int sel_netnode_avc_callback(u32 event) | |
| 302 | 301 | { |
| 303 | 302 | if (event == AVC_CALLBACK_RESET) { |
| 304 | 303 | sel_netnode_flush(); |
| @@ -320,8 +319,7 @@ static __init int sel_netnode_init(void) · 15 unmodified lines | ||
| 320 | 319 | sel_netnode_hash[iter].size = 0; |
| 321 | 320 | } |
| 322 | 321 | |
| 323 | − ret = avc_add_callback(sel_netnode_avc_callback, AVC_CALLBACK_RESET, | |
| 324 | − SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0); | |
| 322 | + ret = avc_add_callback(sel_netnode_avc_callback, AVC_CALLBACK_RESET); | |
| 325 | 323 | if (ret != 0) |
| 326 | 324 | panic("avc_add_callback() failed, error %d\n", ret); |
| 327 | 325 | |
| @@ -234,8 +234,7 @@ static void sel_netport_flush(void) · 233 unmodified lines | ||
| 234 | 234 | spin_unlock_bh(&sel_netport_lock); |
| 235 | 235 | } |
| 236 | 236 | |
| 237 | −static int sel_netport_avc_callback(u32 event, u32 ssid, u32 tsid, | |
| 238 | − u16 class, u32 perms, u32 *retained) | |
| 237 | +static int sel_netport_avc_callback(u32 event) | |
| 239 | 238 | { |
| 240 | 239 | if (event == AVC_CALLBACK_RESET) { |
| 241 | 240 | sel_netport_flush(); |
| @@ -257,8 +256,7 @@ static __init int sel_netport_init(void) · 15 unmodified lines | ||
| 257 | 256 | sel_netport_hash[iter].size = 0; |
| 258 | 257 | } |
| 259 | 258 | |
| 260 | − ret = avc_add_callback(sel_netport_avc_callback, AVC_CALLBACK_RESET, | |
| 261 | − SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0); | |
| 259 | + ret = avc_add_callback(sel_netport_avc_callback, AVC_CALLBACK_RESET); | |
| 262 | 260 | if (ret != 0) |
| 263 | 261 | panic("avc_add_callback() failed, error %d\n", ret); |
| 264 | 262 | |
| @@ -496,6 +496,7 @@ static const struct file_operations sel_policy_ops = { · 495 unmodified lines | ||
| 496 | 496 | .read = sel_read_policy, |
| 497 | 497 | .mmap = sel_mmap_policy, |
| 498 | 498 | .release = sel_release_policy, |
| 499 | + .llseek = generic_file_llseek, | |
| 499 | 500 | }; |
| 500 | 501 | |
| 501 | 502 | static ssize_t sel_write_load(struct file *file, const char __user *buf, |
| @@ -1232,6 +1233,7 @@ static int sel_make_bools(void) · 730 unmodified lines | ||
| 1232 | 1233 | kfree(bool_pending_names[i]); |
| 1233 | 1234 | kfree(bool_pending_names); |
| 1234 | 1235 | kfree(bool_pending_values); |
| 1236 | + bool_num = 0; | |
| 1235 | 1237 | bool_pending_names = NULL; |
| 1236 | 1238 | bool_pending_values = NULL; |
| 1237 | 1239 | |
| @@ -1532,11 +1534,6 @@ static int sel_make_initcon_files(struct dentry *dir) · 294 unmodified lines | ||
| 1532 | 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 | 1537 | static inline unsigned long sel_class_to_ino(u16 class) |
| 1541 | 1538 | { |
| 1542 | 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) · 1 unmodified line | ||
| 1544 | 1541 | |
| 1545 | 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 | 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) · 280 unmodified lines | ||
| 1831 | 1828 | [SEL_REJECT_UNKNOWN] = {"reject_unknown", &sel_handle_unknown_ops, S_IRUGO}, |
| 1832 | 1829 | [SEL_DENY_UNKNOWN] = {"deny_unknown", &sel_handle_unknown_ops, S_IRUGO}, |
| 1833 | 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 | 1832 | /* last one */ {""} |
| 1836 | 1833 | }; |
| 1837 | 1834 | ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files); |
| @@ -74,6 +74,26 @@ out: · 73 unmodified lines | ||
| 74 | 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 | 97 | static inline int mls_context_cmp(struct context *c1, struct context *c2) |
| 78 | 98 | { |
| 79 | 99 | return ((c1->range.level[0].sens == c2->range.level[0].sens) && |
| @@ -517,6 +517,8 @@ int mls_compute_sid(struct context *scontext, · 516 unmodified lines | ||
| 517 | 517 | { |
| 518 | 518 | struct range_trans rtr; |
| 519 | 519 | struct mls_range *r; |
| 520 | + struct class_datum *cladatum; | |
| 521 | + int default_range = 0; | |
| 520 | 522 | |
| 521 | 523 | if (!policydb.mls_enabled) |
| 522 | 524 | return 0; |
| @@ -530,6 +532,28 @@ int mls_compute_sid(struct context *scontext, · 7 unmodified lines | ||
| 530 | 532 | r = hashtab_search(policydb.range_tr, &rtr); |
| 531 | 533 | if (r) |
| 532 | 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 | 557 | /* Fallthrough */ |
| 534 | 558 | case AVTAB_CHANGE: |
| 535 | 559 | if ((tclass == policydb.process_class) || (sock == true)) |
| @@ -133,6 +133,16 @@ static struct policydb_compat_info policydb_compat[] = { · 132 unmodified lines | ||
| 133 | 133 | .sym_num = SYM_NUM, |
| 134 | 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 | 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) · 1167 unmodified lines | ||
| 1306 | 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 | 1336 | rc = hashtab_insert(h, key, cladatum); |
| 1310 | 1337 | if (rc) |
| 1311 | 1338 | goto bad; |
| @@ -2832,6 +2859,23 @@ static int class_write(void *vkey, void *datum, void *ptr) · 1520 unmodified lines | ||
| 2832 | 2859 | if (rc) |
| 2833 | 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 | 2879 | return 0; |
| 2836 | 2880 | } |
| 2837 | 2881 | |
| @@ -60,6 +60,20 @@ struct class_datum { · 59 unmodified lines | ||
| 60 | 60 | struct symtab permissions; /* class-specific permission symbol table */ |
| 61 | 61 | struct constraint_node *constraints; /* constraints on class permissions */ |
| 62 | 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 | 79 | /* Role attributes */ |
| @@ -1018,9 +1018,11 @@ static int context_struct_to_string(struct context *context, char **scontext, u3 · 1017 unmodified lines | ||
| 1018 | 1018 | |
| 1019 | 1019 | if (context->len) { |
| 1020 | 1020 | *scontext_len = context->len; |
| 1021 | − *scontext = kstrdup(context->str, GFP_ATOMIC); | |
| 1022 | − if (!(*scontext)) | |
| 1023 | − return -ENOMEM; | |
| 1021 | + if (scontext) { | |
| 1022 | + *scontext = kstrdup(context->str, GFP_ATOMIC); | |
| 1023 | + if (!(*scontext)) | |
| 1024 | + return -ENOMEM; | |
| 1025 | + } | |
| 1024 | 1026 | return 0; |
| 1025 | 1027 | } |
| 1026 | 1028 | |
| @@ -1389,6 +1391,7 @@ static int security_compute_sid(u32 ssid, · 362 unmodified lines | ||
| 1389 | 1391 | u32 *out_sid, |
| 1390 | 1392 | bool kern) |
| 1391 | 1393 | { |
| 1394 | + struct class_datum *cladatum = NULL; | |
| 1392 | 1395 | struct context *scontext = NULL, *tcontext = NULL, newcontext; |
| 1393 | 1396 | struct role_trans *roletr = NULL; |
| 1394 | 1397 | struct avtab_key avkey; |
| @@ -1437,12 +1440,20 @@ static int security_compute_sid(u32 ssid, · 42 unmodified lines | ||
| 1437 | 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 | 1446 | /* Set the user identity. */ |
| 1441 | 1447 | switch (specified) { |
| 1442 | 1448 | case AVTAB_TRANSITION: |
| 1443 | 1449 | case AVTAB_CHANGE: |
| 1444 | − /* Use the process user identity. */ | |
| 1445 | − newcontext.user = scontext->user; | |
| 1450 | + if (cladatum && cladatum->default_user == DEFAULT_TARGET) { | |
| 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 | 1457 | break; |
| 1447 | 1458 | case AVTAB_MEMBER: |
| 1448 | 1459 | /* Use the related object owner. */ |
| @@ -1450,16 +1461,31 @@ static int security_compute_sid(u32 ssid, · 1 unmodified line | ||
| 1450 | 1461 | break; |
| 1451 | 1462 | } |
| 1452 | 1463 | |
| 1453 | − /* Set the role and type to default values. */ | |
| 1454 | − if ((tclass == policydb.process_class) || (sock == true)) { | |
| 1455 | − /* Use the current role and type of process. */ | |
| 1464 | + /* Set the role to default values. */ | |
| 1465 | + if (cladatum && cladatum->default_role == DEFAULT_SOURCE) { | |
| 1456 | 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 | 1469 | } else { |
| 1459 | − /* Use the well-defined object role. */ | |
| 1460 | − newcontext.role = OBJECT_R_VAL; | |
| 1461 | − /* Use the type of the related object. */ | |
| 1470 | + if ((tclass == policydb.process_class) || (sock == true)) | |
| 1471 | + newcontext.role = scontext->role; | |
| 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 | 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 | 1491 | /* Look for a type transition/member/change rule. */ |
| @@ -3018,8 +3044,7 @@ out: · 1552 unmodified lines | ||
| 3018 | 3044 | |
| 3019 | 3045 | static int (*aurule_callback)(void) = audit_update_lsm_rules; |
| 3020 | 3046 | |
| 3021 | −static int aurule_avc_callback(u32 event, u32 ssid, u32 tsid, | |
| 3022 | − u16 class, u32 perms, u32 *retained) | |
| 3047 | +static int aurule_avc_callback(u32 event) | |
| 3023 | 3048 | { |
| 3024 | 3049 | int err = 0; |
| 3025 | 3050 | |
| @@ -3032,8 +3057,7 @@ static int __init aurule_init(void) · 6 unmodified lines | ||
| 3032 | 3057 | { |
| 3033 | 3058 | int err; |
| 3034 | 3059 | |
| 3035 | − err = avc_add_callback(aurule_avc_callback, AVC_CALLBACK_RESET, | |
| 3036 | − SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0); | |
| 3060 | + err = avc_add_callback(aurule_avc_callback, AVC_CALLBACK_RESET); | |
| 3037 | 3061 | if (err) |
| 3038 | 3062 | panic("avc_add_callback() failed, error %d\n", err); |
| 3039 | 3063 | |
| @@ -304,7 +304,7 @@ void smack_log(char *subject_label, char *object_label, · 303 unmodified lines | ||
| 304 | 304 | static inline void smk_ad_init(struct smk_audit_info *a, const char *func, |
| 305 | 305 | char type) |
| 306 | 306 | { |
| 307 | − memset(a, 0, sizeof(*a)); | |
| 307 | + memset(&a->sad, 0, sizeof(a->sad)); | |
| 308 | 308 | a->a.type = type; |
| 309 | 309 | a->a.smack_audit_data = &a->sad; |
| 310 | 310 | a->a.smack_audit_data->function = func; |
| @@ -1359,7 +1359,7 @@ static int smack_file_receive(struct file *file) · 1358 unmodified lines | ||
| 1359 | 1359 | } |
| 1360 | 1360 | |
| 1361 | 1361 | /** |
| 1362 | − * smack_dentry_open - Smack dentry open processing | |
| 1362 | + * smack_file_open - Smack dentry open processing | |
| 1363 | 1363 | * @file: the object |
| 1364 | 1364 | * @cred: unused |
| 1365 | 1365 | * |
| @@ -1367,7 +1367,7 @@ static int smack_file_receive(struct file *file) · 1 unmodified line | ||
| 1367 | 1367 | * |
| 1368 | 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 | 1372 | struct inode_smack *isp = file->f_path.dentry->d_inode->i_security; |
| 1373 | 1373 | |
| @@ -3487,7 +3487,7 @@ struct security_operations smack_ops = { · 2113 unmodified lines | ||
| 3487 | 3487 | .file_send_sigiotask = smack_file_send_sigiotask, |
| 3488 | 3488 | .file_receive = smack_file_receive, |
| 3489 | 3489 | |
| 3490 | − .dentry_open = smack_dentry_open, | |
| 3490 | + .file_open = smack_file_open, | |
| 3491 | 3491 | |
| 3492 | 3492 | .cred_alloc_blank = smack_cred_alloc_blank, |
| 3493 | 3493 | .cred_free = smack_cred_free, |
| @@ -319,14 +319,14 @@ static int tomoyo_file_fcntl(struct file *file, unsigned int cmd, · 318 unmodified lines | ||
| 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 | 324 | * @f: Pointer to "struct file". |
| 325 | 325 | * @cred: Pointer to "struct cred". |
| 326 | 326 | * |
| 327 | 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 | 331 | int flags = f->f_flags; |
| 332 | 332 | /* Don't check read permission here if called from do_execve(). */ |
| @@ -510,7 +510,7 @@ static struct security_operations tomoyo_security_ops = { · 177 unmodified lines | ||
| 510 | 510 | .bprm_set_creds = tomoyo_bprm_set_creds, |
| 511 | 511 | .bprm_check_security = tomoyo_bprm_check_security, |
| 512 | 512 | .file_fcntl = tomoyo_file_fcntl, |
| 513 | − .dentry_open = tomoyo_dentry_open, | |
| 513 | + .file_open = tomoyo_file_open, | |
| 514 | 514 | .path_truncate = tomoyo_path_truncate, |
| 515 | 515 | .path_unlink = tomoyo_path_unlink, |
| 516 | 516 | .path_mkdir = tomoyo_path_mkdir, |