diff options
author | Jonathan Corbet <corbet@lwn.net> | 2008-07-14 17:29:34 -0400 |
---|---|---|
committer | Jonathan Corbet <corbet@lwn.net> | 2008-07-14 17:29:34 -0400 |
commit | 2fceef397f9880b212a74c418290ce69e7ac00eb (patch) | |
tree | d9cc09ab992825ef7fede4a688103503e3caf655 /security | |
parent | feae1ef116ed381625d3731c5ae4f4ebcb3fa302 (diff) | |
parent | bce7f793daec3e65ec5c5705d2457b81fe7b5725 (diff) |
Merge commit 'v2.6.26' into bkl-removal
Diffstat (limited to 'security')
-rw-r--r-- | security/commoncap.c | 13 | ||||
-rw-r--r-- | security/device_cgroup.c | 44 | ||||
-rw-r--r-- | security/dummy.c | 24 | ||||
-rw-r--r-- | security/keys/internal.h | 1 | ||||
-rw-r--r-- | security/smack/smack_lsm.c | 12 |
5 files changed, 76 insertions, 18 deletions
diff --git a/security/commoncap.c b/security/commoncap.c index 5edabc7542ae..33d343308413 100644 --- a/security/commoncap.c +++ b/security/commoncap.c | |||
@@ -103,10 +103,16 @@ static inline int cap_inh_is_capped(void) | |||
103 | return (cap_capable(current, CAP_SETPCAP) != 0); | 103 | return (cap_capable(current, CAP_SETPCAP) != 0); |
104 | } | 104 | } |
105 | 105 | ||
106 | static inline int cap_limit_ptraced_target(void) { return 1; } | ||
107 | |||
106 | #else /* ie., ndef CONFIG_SECURITY_FILE_CAPABILITIES */ | 108 | #else /* ie., ndef CONFIG_SECURITY_FILE_CAPABILITIES */ |
107 | 109 | ||
108 | static inline int cap_block_setpcap(struct task_struct *t) { return 0; } | 110 | static inline int cap_block_setpcap(struct task_struct *t) { return 0; } |
109 | static inline int cap_inh_is_capped(void) { return 1; } | 111 | static inline int cap_inh_is_capped(void) { return 1; } |
112 | static inline int cap_limit_ptraced_target(void) | ||
113 | { | ||
114 | return !capable(CAP_SETPCAP); | ||
115 | } | ||
110 | 116 | ||
111 | #endif /* def CONFIG_SECURITY_FILE_CAPABILITIES */ | 117 | #endif /* def CONFIG_SECURITY_FILE_CAPABILITIES */ |
112 | 118 | ||
@@ -342,9 +348,10 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe) | |||
342 | bprm->e_uid = current->uid; | 348 | bprm->e_uid = current->uid; |
343 | bprm->e_gid = current->gid; | 349 | bprm->e_gid = current->gid; |
344 | } | 350 | } |
345 | if (!capable (CAP_SETPCAP)) { | 351 | if (cap_limit_ptraced_target()) { |
346 | new_permitted = cap_intersect (new_permitted, | 352 | new_permitted = |
347 | current->cap_permitted); | 353 | cap_intersect(new_permitted, |
354 | current->cap_permitted); | ||
348 | } | 355 | } |
349 | } | 356 | } |
350 | } | 357 | } |
diff --git a/security/device_cgroup.c b/security/device_cgroup.c index 4ea583689eec..ddd92cec78ed 100644 --- a/security/device_cgroup.c +++ b/security/device_cgroup.c | |||
@@ -49,10 +49,14 @@ struct dev_cgroup { | |||
49 | spinlock_t lock; | 49 | spinlock_t lock; |
50 | }; | 50 | }; |
51 | 51 | ||
52 | static inline struct dev_cgroup *css_to_devcgroup(struct cgroup_subsys_state *s) | ||
53 | { | ||
54 | return container_of(s, struct dev_cgroup, css); | ||
55 | } | ||
56 | |||
52 | static inline struct dev_cgroup *cgroup_to_devcgroup(struct cgroup *cgroup) | 57 | static inline struct dev_cgroup *cgroup_to_devcgroup(struct cgroup *cgroup) |
53 | { | 58 | { |
54 | return container_of(cgroup_subsys_state(cgroup, devices_subsys_id), | 59 | return css_to_devcgroup(cgroup_subsys_state(cgroup, devices_subsys_id)); |
55 | struct dev_cgroup, css); | ||
56 | } | 60 | } |
57 | 61 | ||
58 | struct cgroup_subsys devices_subsys; | 62 | struct cgroup_subsys devices_subsys; |
@@ -102,7 +106,7 @@ free_and_exit: | |||
102 | static int dev_whitelist_add(struct dev_cgroup *dev_cgroup, | 106 | static int dev_whitelist_add(struct dev_cgroup *dev_cgroup, |
103 | struct dev_whitelist_item *wh) | 107 | struct dev_whitelist_item *wh) |
104 | { | 108 | { |
105 | struct dev_whitelist_item *whcopy; | 109 | struct dev_whitelist_item *whcopy, *walk; |
106 | 110 | ||
107 | whcopy = kmalloc(sizeof(*whcopy), GFP_KERNEL); | 111 | whcopy = kmalloc(sizeof(*whcopy), GFP_KERNEL); |
108 | if (!whcopy) | 112 | if (!whcopy) |
@@ -110,7 +114,21 @@ static int dev_whitelist_add(struct dev_cgroup *dev_cgroup, | |||
110 | 114 | ||
111 | memcpy(whcopy, wh, sizeof(*whcopy)); | 115 | memcpy(whcopy, wh, sizeof(*whcopy)); |
112 | spin_lock(&dev_cgroup->lock); | 116 | spin_lock(&dev_cgroup->lock); |
113 | list_add_tail(&whcopy->list, &dev_cgroup->whitelist); | 117 | list_for_each_entry(walk, &dev_cgroup->whitelist, list) { |
118 | if (walk->type != wh->type) | ||
119 | continue; | ||
120 | if (walk->major != wh->major) | ||
121 | continue; | ||
122 | if (walk->minor != wh->minor) | ||
123 | continue; | ||
124 | |||
125 | walk->access |= wh->access; | ||
126 | kfree(whcopy); | ||
127 | whcopy = NULL; | ||
128 | } | ||
129 | |||
130 | if (whcopy != NULL) | ||
131 | list_add_tail(&whcopy->list, &dev_cgroup->whitelist); | ||
114 | spin_unlock(&dev_cgroup->lock); | 132 | spin_unlock(&dev_cgroup->lock); |
115 | return 0; | 133 | return 0; |
116 | } | 134 | } |
@@ -204,7 +222,7 @@ static void devcgroup_destroy(struct cgroup_subsys *ss, | |||
204 | #define DEVCG_DENY 2 | 222 | #define DEVCG_DENY 2 |
205 | #define DEVCG_LIST 3 | 223 | #define DEVCG_LIST 3 |
206 | 224 | ||
207 | #define MAJMINLEN 10 | 225 | #define MAJMINLEN 13 |
208 | #define ACCLEN 4 | 226 | #define ACCLEN 4 |
209 | 227 | ||
210 | static void set_access(char *acc, short access) | 228 | static void set_access(char *acc, short access) |
@@ -236,7 +254,7 @@ static void set_majmin(char *str, unsigned m) | |||
236 | if (m == ~0) | 254 | if (m == ~0) |
237 | sprintf(str, "*"); | 255 | sprintf(str, "*"); |
238 | else | 256 | else |
239 | snprintf(str, MAJMINLEN, "%d", m); | 257 | snprintf(str, MAJMINLEN, "%u", m); |
240 | } | 258 | } |
241 | 259 | ||
242 | static int devcgroup_seq_read(struct cgroup *cgroup, struct cftype *cft, | 260 | static int devcgroup_seq_read(struct cgroup *cgroup, struct cftype *cft, |
@@ -282,7 +300,7 @@ static int may_access_whitelist(struct dev_cgroup *c, | |||
282 | continue; | 300 | continue; |
283 | if (whitem->minor != ~0 && whitem->minor != refwh->minor) | 301 | if (whitem->minor != ~0 && whitem->minor != refwh->minor) |
284 | continue; | 302 | continue; |
285 | if (refwh->access & (~(whitem->access | ACC_MASK))) | 303 | if (refwh->access & (~whitem->access)) |
286 | continue; | 304 | continue; |
287 | return 1; | 305 | return 1; |
288 | } | 306 | } |
@@ -364,6 +382,8 @@ static ssize_t devcgroup_access_write(struct cgroup *cgroup, struct cftype *cft, | |||
364 | case 'a': | 382 | case 'a': |
365 | wh.type = DEV_ALL; | 383 | wh.type = DEV_ALL; |
366 | wh.access = ACC_MASK; | 384 | wh.access = ACC_MASK; |
385 | wh.major = ~0; | ||
386 | wh.minor = ~0; | ||
367 | goto handle; | 387 | goto handle; |
368 | case 'b': | 388 | case 'b': |
369 | wh.type = DEV_BLOCK; | 389 | wh.type = DEV_BLOCK; |
@@ -502,7 +522,6 @@ struct cgroup_subsys devices_subsys = { | |||
502 | 522 | ||
503 | int devcgroup_inode_permission(struct inode *inode, int mask) | 523 | int devcgroup_inode_permission(struct inode *inode, int mask) |
504 | { | 524 | { |
505 | struct cgroup *cgroup; | ||
506 | struct dev_cgroup *dev_cgroup; | 525 | struct dev_cgroup *dev_cgroup; |
507 | struct dev_whitelist_item *wh; | 526 | struct dev_whitelist_item *wh; |
508 | 527 | ||
@@ -511,8 +530,8 @@ int devcgroup_inode_permission(struct inode *inode, int mask) | |||
511 | return 0; | 530 | return 0; |
512 | if (!S_ISBLK(inode->i_mode) && !S_ISCHR(inode->i_mode)) | 531 | if (!S_ISBLK(inode->i_mode) && !S_ISCHR(inode->i_mode)) |
513 | return 0; | 532 | return 0; |
514 | cgroup = task_cgroup(current, devices_subsys.subsys_id); | 533 | dev_cgroup = css_to_devcgroup(task_subsys_state(current, |
515 | dev_cgroup = cgroup_to_devcgroup(cgroup); | 534 | devices_subsys_id)); |
516 | if (!dev_cgroup) | 535 | if (!dev_cgroup) |
517 | return 0; | 536 | return 0; |
518 | 537 | ||
@@ -543,12 +562,11 @@ acc_check: | |||
543 | 562 | ||
544 | int devcgroup_inode_mknod(int mode, dev_t dev) | 563 | int devcgroup_inode_mknod(int mode, dev_t dev) |
545 | { | 564 | { |
546 | struct cgroup *cgroup; | ||
547 | struct dev_cgroup *dev_cgroup; | 565 | struct dev_cgroup *dev_cgroup; |
548 | struct dev_whitelist_item *wh; | 566 | struct dev_whitelist_item *wh; |
549 | 567 | ||
550 | cgroup = task_cgroup(current, devices_subsys.subsys_id); | 568 | dev_cgroup = css_to_devcgroup(task_subsys_state(current, |
551 | dev_cgroup = cgroup_to_devcgroup(cgroup); | 569 | devices_subsys_id)); |
552 | if (!dev_cgroup) | 570 | if (!dev_cgroup) |
553 | return 0; | 571 | return 0; |
554 | 572 | ||
diff --git a/security/dummy.c b/security/dummy.c index f50c6c3c32c9..b8916883b77f 100644 --- a/security/dummy.c +++ b/security/dummy.c | |||
@@ -27,6 +27,8 @@ | |||
27 | #include <linux/hugetlb.h> | 27 | #include <linux/hugetlb.h> |
28 | #include <linux/ptrace.h> | 28 | #include <linux/ptrace.h> |
29 | #include <linux/file.h> | 29 | #include <linux/file.h> |
30 | #include <linux/prctl.h> | ||
31 | #include <linux/securebits.h> | ||
30 | 32 | ||
31 | static int dummy_ptrace (struct task_struct *parent, struct task_struct *child) | 33 | static int dummy_ptrace (struct task_struct *parent, struct task_struct *child) |
32 | { | 34 | { |
@@ -607,7 +609,27 @@ static int dummy_task_kill (struct task_struct *p, struct siginfo *info, | |||
607 | static int dummy_task_prctl (int option, unsigned long arg2, unsigned long arg3, | 609 | static int dummy_task_prctl (int option, unsigned long arg2, unsigned long arg3, |
608 | unsigned long arg4, unsigned long arg5, long *rc_p) | 610 | unsigned long arg4, unsigned long arg5, long *rc_p) |
609 | { | 611 | { |
610 | return 0; | 612 | switch (option) { |
613 | case PR_CAPBSET_READ: | ||
614 | *rc_p = (cap_valid(arg2) ? 1 : -EINVAL); | ||
615 | break; | ||
616 | case PR_GET_KEEPCAPS: | ||
617 | *rc_p = issecure(SECURE_KEEP_CAPS); | ||
618 | break; | ||
619 | case PR_SET_KEEPCAPS: | ||
620 | if (arg2 > 1) | ||
621 | *rc_p = -EINVAL; | ||
622 | else if (arg2) | ||
623 | current->securebits |= issecure_mask(SECURE_KEEP_CAPS); | ||
624 | else | ||
625 | current->securebits &= | ||
626 | ~issecure_mask(SECURE_KEEP_CAPS); | ||
627 | break; | ||
628 | default: | ||
629 | return 0; | ||
630 | } | ||
631 | |||
632 | return 1; | ||
611 | } | 633 | } |
612 | 634 | ||
613 | static void dummy_task_reparent_to_init (struct task_struct *p) | 635 | static void dummy_task_reparent_to_init (struct task_struct *p) |
diff --git a/security/keys/internal.h b/security/keys/internal.h index 8c05587f5018..b39f5c2e2c4b 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h | |||
@@ -78,7 +78,6 @@ extern unsigned key_quota_maxbytes; | |||
78 | 78 | ||
79 | extern struct rb_root key_serial_tree; | 79 | extern struct rb_root key_serial_tree; |
80 | extern spinlock_t key_serial_lock; | 80 | extern spinlock_t key_serial_lock; |
81 | extern struct semaphore key_alloc_sem; | ||
82 | extern struct mutex key_construction_mutex; | 81 | extern struct mutex key_construction_mutex; |
83 | extern wait_queue_head_t request_key_conswq; | 82 | extern wait_queue_head_t request_key_conswq; |
84 | 83 | ||
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index b5c8f9237008..4a09293efa00 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
@@ -1881,6 +1881,18 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
1881 | final = sbsp->smk_default; | 1881 | final = sbsp->smk_default; |
1882 | 1882 | ||
1883 | /* | 1883 | /* |
1884 | * If this is the root inode the superblock | ||
1885 | * may be in the process of initialization. | ||
1886 | * If that is the case use the root value out | ||
1887 | * of the superblock. | ||
1888 | */ | ||
1889 | if (opt_dentry->d_parent == opt_dentry) { | ||
1890 | isp->smk_inode = sbsp->smk_root; | ||
1891 | isp->smk_flags |= SMK_INODE_INSTANT; | ||
1892 | goto unlockandout; | ||
1893 | } | ||
1894 | |||
1895 | /* | ||
1884 | * This is pretty hackish. | 1896 | * This is pretty hackish. |
1885 | * Casey says that we shouldn't have to do | 1897 | * Casey says that we shouldn't have to do |
1886 | * file system specific code, but it does help | 1898 | * file system specific code, but it does help |