diff options
Diffstat (limited to 'security')
-rw-r--r-- | security/inode.c | 33 | ||||
-rw-r--r-- | security/security.c | 8 | ||||
-rw-r--r-- | security/selinux/hooks.c | 45 | ||||
-rw-r--r-- | security/selinux/ss/avtab.c | 8 | ||||
-rw-r--r-- | security/selinux/ss/conditional.c | 18 | ||||
-rw-r--r-- | security/selinux/ss/conditional.h | 2 | ||||
-rw-r--r-- | security/selinux/ss/ebitmap.c | 4 | ||||
-rw-r--r-- | security/selinux/ss/hashtab.c | 6 | ||||
-rw-r--r-- | security/selinux/ss/mls.c | 14 | ||||
-rw-r--r-- | security/selinux/ss/policydb.c | 20 | ||||
-rw-r--r-- | security/selinux/ss/services.c | 8 | ||||
-rw-r--r-- | security/selinux/ss/sidtab.c | 12 | ||||
-rw-r--r-- | security/smack/smack.h | 1 | ||||
-rw-r--r-- | security/smack/smack_access.c | 10 | ||||
-rw-r--r-- | security/smack/smackfs.c | 92 |
15 files changed, 193 insertions, 88 deletions
diff --git a/security/inode.c b/security/inode.c index acc6cf0d7900..ca4958ebad8d 100644 --- a/security/inode.c +++ b/security/inode.c | |||
@@ -190,7 +190,7 @@ static int create_by_name(const char *name, mode_t mode, | |||
190 | * @name: a pointer to a string containing the name of the file to create. | 190 | * @name: a pointer to a string containing the name of the file to create. |
191 | * @mode: the permission that the file should have | 191 | * @mode: the permission that the file should have |
192 | * @parent: a pointer to the parent dentry for this file. This should be a | 192 | * @parent: a pointer to the parent dentry for this file. This should be a |
193 | * directory dentry if set. If this paramater is NULL, then the | 193 | * directory dentry if set. If this parameter is %NULL, then the |
194 | * file will be created in the root of the securityfs filesystem. | 194 | * file will be created in the root of the securityfs filesystem. |
195 | * @data: a pointer to something that the caller will want to get to later | 195 | * @data: a pointer to something that the caller will want to get to later |
196 | * on. The inode.i_private pointer will point to this value on | 196 | * on. The inode.i_private pointer will point to this value on |
@@ -199,18 +199,18 @@ static int create_by_name(const char *name, mode_t mode, | |||
199 | * this file. | 199 | * this file. |
200 | * | 200 | * |
201 | * This is the basic "create a file" function for securityfs. It allows for a | 201 | * This is the basic "create a file" function for securityfs. It allows for a |
202 | * wide range of flexibility in createing a file, or a directory (if you | 202 | * wide range of flexibility in creating a file, or a directory (if you |
203 | * want to create a directory, the securityfs_create_dir() function is | 203 | * want to create a directory, the securityfs_create_dir() function is |
204 | * recommended to be used instead.) | 204 | * recommended to be used instead). |
205 | * | 205 | * |
206 | * This function will return a pointer to a dentry if it succeeds. This | 206 | * This function returns a pointer to a dentry if it succeeds. This |
207 | * pointer must be passed to the securityfs_remove() function when the file is | 207 | * pointer must be passed to the securityfs_remove() function when the file is |
208 | * to be removed (no automatic cleanup happens if your module is unloaded, | 208 | * to be removed (no automatic cleanup happens if your module is unloaded, |
209 | * you are responsible here.) If an error occurs, NULL will be returned. | 209 | * you are responsible here). If an error occurs, %NULL is returned. |
210 | * | 210 | * |
211 | * If securityfs is not enabled in the kernel, the value -ENODEV will be | 211 | * If securityfs is not enabled in the kernel, the value %-ENODEV is |
212 | * returned. It is not wise to check for this value, but rather, check for | 212 | * returned. It is not wise to check for this value, but rather, check for |
213 | * NULL or !NULL instead as to eliminate the need for #ifdef in the calling | 213 | * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling |
214 | * code. | 214 | * code. |
215 | */ | 215 | */ |
216 | struct dentry *securityfs_create_file(const char *name, mode_t mode, | 216 | struct dentry *securityfs_create_file(const char *name, mode_t mode, |
@@ -252,19 +252,19 @@ EXPORT_SYMBOL_GPL(securityfs_create_file); | |||
252 | * @name: a pointer to a string containing the name of the directory to | 252 | * @name: a pointer to a string containing the name of the directory to |
253 | * create. | 253 | * create. |
254 | * @parent: a pointer to the parent dentry for this file. This should be a | 254 | * @parent: a pointer to the parent dentry for this file. This should be a |
255 | * directory dentry if set. If this paramater is NULL, then the | 255 | * directory dentry if set. If this parameter is %NULL, then the |
256 | * directory will be created in the root of the securityfs filesystem. | 256 | * directory will be created in the root of the securityfs filesystem. |
257 | * | 257 | * |
258 | * This function creates a directory in securityfs with the given name. | 258 | * This function creates a directory in securityfs with the given @name. |
259 | * | 259 | * |
260 | * This function will return a pointer to a dentry if it succeeds. This | 260 | * This function returns a pointer to a dentry if it succeeds. This |
261 | * pointer must be passed to the securityfs_remove() function when the file is | 261 | * pointer must be passed to the securityfs_remove() function when the file is |
262 | * to be removed (no automatic cleanup happens if your module is unloaded, | 262 | * to be removed (no automatic cleanup happens if your module is unloaded, |
263 | * you are responsible here.) If an error occurs, NULL will be returned. | 263 | * you are responsible here). If an error occurs, %NULL will be returned. |
264 | * | 264 | * |
265 | * If securityfs is not enabled in the kernel, the value -ENODEV will be | 265 | * If securityfs is not enabled in the kernel, the value %-ENODEV is |
266 | * returned. It is not wise to check for this value, but rather, check for | 266 | * returned. It is not wise to check for this value, but rather, check for |
267 | * NULL or !NULL instead as to eliminate the need for #ifdef in the calling | 267 | * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling |
268 | * code. | 268 | * code. |
269 | */ | 269 | */ |
270 | struct dentry *securityfs_create_dir(const char *name, struct dentry *parent) | 270 | struct dentry *securityfs_create_dir(const char *name, struct dentry *parent) |
@@ -278,16 +278,15 @@ EXPORT_SYMBOL_GPL(securityfs_create_dir); | |||
278 | /** | 278 | /** |
279 | * securityfs_remove - removes a file or directory from the securityfs filesystem | 279 | * securityfs_remove - removes a file or directory from the securityfs filesystem |
280 | * | 280 | * |
281 | * @dentry: a pointer to a the dentry of the file or directory to be | 281 | * @dentry: a pointer to a the dentry of the file or directory to be removed. |
282 | * removed. | ||
283 | * | 282 | * |
284 | * This function removes a file or directory in securityfs that was previously | 283 | * This function removes a file or directory in securityfs that was previously |
285 | * created with a call to another securityfs function (like | 284 | * created with a call to another securityfs function (like |
286 | * securityfs_create_file() or variants thereof.) | 285 | * securityfs_create_file() or variants thereof.) |
287 | * | 286 | * |
288 | * This function is required to be called in order for the file to be | 287 | * This function is required to be called in order for the file to be |
289 | * removed, no automatic cleanup of files will happen when a module is | 288 | * removed. No automatic cleanup of files will happen when a module is |
290 | * removed, you are responsible here. | 289 | * removed; you are responsible here. |
291 | */ | 290 | */ |
292 | void securityfs_remove(struct dentry *dentry) | 291 | void securityfs_remove(struct dentry *dentry) |
293 | { | 292 | { |
diff --git a/security/security.c b/security/security.c index 3a4b4f55b33f..255b08559b2b 100644 --- a/security/security.c +++ b/security/security.c | |||
@@ -82,8 +82,8 @@ __setup("security=", choose_lsm); | |||
82 | * | 82 | * |
83 | * Return true if: | 83 | * Return true if: |
84 | * -The passed LSM is the one chosen by user at boot time, | 84 | * -The passed LSM is the one chosen by user at boot time, |
85 | * -or user didsn't specify a specific LSM and we're the first to ask | 85 | * -or user didn't specify a specific LSM and we're the first to ask |
86 | * for registeration permissoin, | 86 | * for registration permission, |
87 | * -or the passed LSM is currently loaded. | 87 | * -or the passed LSM is currently loaded. |
88 | * Otherwise, return false. | 88 | * Otherwise, return false. |
89 | */ | 89 | */ |
@@ -101,13 +101,13 @@ int __init security_module_enable(struct security_operations *ops) | |||
101 | * register_security - registers a security framework with the kernel | 101 | * register_security - registers a security framework with the kernel |
102 | * @ops: a pointer to the struct security_options that is to be registered | 102 | * @ops: a pointer to the struct security_options that is to be registered |
103 | * | 103 | * |
104 | * This function is to allow a security module to register itself with the | 104 | * This function allows a security module to register itself with the |
105 | * kernel security subsystem. Some rudimentary checking is done on the @ops | 105 | * kernel security subsystem. Some rudimentary checking is done on the @ops |
106 | * value passed to this function. You'll need to check first if your LSM | 106 | * value passed to this function. You'll need to check first if your LSM |
107 | * is allowed to register its @ops by calling security_module_enable(@ops). | 107 | * is allowed to register its @ops by calling security_module_enable(@ops). |
108 | * | 108 | * |
109 | * If there is already a security module registered with the kernel, | 109 | * If there is already a security module registered with the kernel, |
110 | * an error will be returned. Otherwise 0 is returned on success. | 110 | * an error will be returned. Otherwise %0 is returned on success. |
111 | */ | 111 | */ |
112 | int register_security(struct security_operations *ops) | 112 | int register_security(struct security_operations *ops) |
113 | { | 113 | { |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 03fc6a81ae32..6b5790bba8f9 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -957,7 +957,8 @@ out_err: | |||
957 | return rc; | 957 | return rc; |
958 | } | 958 | } |
959 | 959 | ||
960 | void selinux_write_opts(struct seq_file *m, struct security_mnt_opts *opts) | 960 | static void selinux_write_opts(struct seq_file *m, |
961 | struct security_mnt_opts *opts) | ||
961 | { | 962 | { |
962 | int i; | 963 | int i; |
963 | char *prefix; | 964 | char *prefix; |
@@ -3548,38 +3549,44 @@ out: | |||
3548 | #endif /* IPV6 */ | 3549 | #endif /* IPV6 */ |
3549 | 3550 | ||
3550 | static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, | 3551 | static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, |
3551 | char **addrp, int src, u8 *proto) | 3552 | char **_addrp, int src, u8 *proto) |
3552 | { | 3553 | { |
3553 | int ret = 0; | 3554 | char *addrp; |
3555 | int ret; | ||
3554 | 3556 | ||
3555 | switch (ad->u.net.family) { | 3557 | switch (ad->u.net.family) { |
3556 | case PF_INET: | 3558 | case PF_INET: |
3557 | ret = selinux_parse_skb_ipv4(skb, ad, proto); | 3559 | ret = selinux_parse_skb_ipv4(skb, ad, proto); |
3558 | if (ret || !addrp) | 3560 | if (ret) |
3559 | break; | 3561 | goto parse_error; |
3560 | *addrp = (char *)(src ? &ad->u.net.v4info.saddr : | 3562 | addrp = (char *)(src ? &ad->u.net.v4info.saddr : |
3561 | &ad->u.net.v4info.daddr); | 3563 | &ad->u.net.v4info.daddr); |
3562 | break; | 3564 | goto okay; |
3563 | 3565 | ||
3564 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 3566 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
3565 | case PF_INET6: | 3567 | case PF_INET6: |
3566 | ret = selinux_parse_skb_ipv6(skb, ad, proto); | 3568 | ret = selinux_parse_skb_ipv6(skb, ad, proto); |
3567 | if (ret || !addrp) | 3569 | if (ret) |
3568 | break; | 3570 | goto parse_error; |
3569 | *addrp = (char *)(src ? &ad->u.net.v6info.saddr : | 3571 | addrp = (char *)(src ? &ad->u.net.v6info.saddr : |
3570 | &ad->u.net.v6info.daddr); | 3572 | &ad->u.net.v6info.daddr); |
3571 | break; | 3573 | goto okay; |
3572 | #endif /* IPV6 */ | 3574 | #endif /* IPV6 */ |
3573 | default: | 3575 | default: |
3574 | break; | 3576 | addrp = NULL; |
3577 | goto okay; | ||
3575 | } | 3578 | } |
3576 | 3579 | ||
3577 | if (unlikely(ret)) | 3580 | parse_error: |
3578 | printk(KERN_WARNING | 3581 | printk(KERN_WARNING |
3579 | "SELinux: failure in selinux_parse_skb()," | 3582 | "SELinux: failure in selinux_parse_skb()," |
3580 | " unable to parse packet\n"); | 3583 | " unable to parse packet\n"); |
3581 | |||
3582 | return ret; | 3584 | return ret; |
3585 | |||
3586 | okay: | ||
3587 | if (_addrp) | ||
3588 | *_addrp = addrp; | ||
3589 | return 0; | ||
3583 | } | 3590 | } |
3584 | 3591 | ||
3585 | /** | 3592 | /** |
diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c index a1be97f8beea..1215b8e47dba 100644 --- a/security/selinux/ss/avtab.c +++ b/security/selinux/ss/avtab.c | |||
@@ -98,7 +98,7 @@ struct avtab_node * | |||
98 | avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, struct avtab_datum *datum) | 98 | avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, struct avtab_datum *datum) |
99 | { | 99 | { |
100 | int hvalue; | 100 | int hvalue; |
101 | struct avtab_node *prev, *cur, *newnode; | 101 | struct avtab_node *prev, *cur; |
102 | u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); | 102 | u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); |
103 | 103 | ||
104 | if (!h || !h->htable) | 104 | if (!h || !h->htable) |
@@ -122,9 +122,7 @@ avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, struct avtab_datu | |||
122 | key->target_class < cur->key.target_class) | 122 | key->target_class < cur->key.target_class) |
123 | break; | 123 | break; |
124 | } | 124 | } |
125 | newnode = avtab_insert_node(h, hvalue, prev, cur, key, datum); | 125 | return avtab_insert_node(h, hvalue, prev, cur, key, datum); |
126 | |||
127 | return newnode; | ||
128 | } | 126 | } |
129 | 127 | ||
130 | struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key) | 128 | struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key) |
@@ -231,7 +229,7 @@ void avtab_destroy(struct avtab *h) | |||
231 | 229 | ||
232 | for (i = 0; i < h->nslot; i++) { | 230 | for (i = 0; i < h->nslot; i++) { |
233 | cur = h->htable[i]; | 231 | cur = h->htable[i]; |
234 | while (cur != NULL) { | 232 | while (cur) { |
235 | temp = cur; | 233 | temp = cur; |
236 | cur = cur->next; | 234 | cur = cur->next; |
237 | kmem_cache_free(avtab_node_cachep, temp); | 235 | kmem_cache_free(avtab_node_cachep, temp); |
diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c index fb4efe4f4bc8..4a4e35cac22b 100644 --- a/security/selinux/ss/conditional.c +++ b/security/selinux/ss/conditional.c | |||
@@ -29,7 +29,7 @@ static int cond_evaluate_expr(struct policydb *p, struct cond_expr *expr) | |||
29 | int s[COND_EXPR_MAXDEPTH]; | 29 | int s[COND_EXPR_MAXDEPTH]; |
30 | int sp = -1; | 30 | int sp = -1; |
31 | 31 | ||
32 | for (cur = expr; cur != NULL; cur = cur->next) { | 32 | for (cur = expr; cur; cur = cur->next) { |
33 | switch (cur->expr_type) { | 33 | switch (cur->expr_type) { |
34 | case COND_BOOL: | 34 | case COND_BOOL: |
35 | if (sp == (COND_EXPR_MAXDEPTH - 1)) | 35 | if (sp == (COND_EXPR_MAXDEPTH - 1)) |
@@ -97,14 +97,14 @@ int evaluate_cond_node(struct policydb *p, struct cond_node *node) | |||
97 | if (new_state == -1) | 97 | if (new_state == -1) |
98 | printk(KERN_ERR "SELinux: expression result was undefined - disabling all rules.\n"); | 98 | printk(KERN_ERR "SELinux: expression result was undefined - disabling all rules.\n"); |
99 | /* turn the rules on or off */ | 99 | /* turn the rules on or off */ |
100 | for (cur = node->true_list; cur != NULL; cur = cur->next) { | 100 | for (cur = node->true_list; cur; cur = cur->next) { |
101 | if (new_state <= 0) | 101 | if (new_state <= 0) |
102 | cur->node->key.specified &= ~AVTAB_ENABLED; | 102 | cur->node->key.specified &= ~AVTAB_ENABLED; |
103 | else | 103 | else |
104 | cur->node->key.specified |= AVTAB_ENABLED; | 104 | cur->node->key.specified |= AVTAB_ENABLED; |
105 | } | 105 | } |
106 | 106 | ||
107 | for (cur = node->false_list; cur != NULL; cur = cur->next) { | 107 | for (cur = node->false_list; cur; cur = cur->next) { |
108 | /* -1 or 1 */ | 108 | /* -1 or 1 */ |
109 | if (new_state) | 109 | if (new_state) |
110 | cur->node->key.specified &= ~AVTAB_ENABLED; | 110 | cur->node->key.specified &= ~AVTAB_ENABLED; |
@@ -128,7 +128,7 @@ int cond_policydb_init(struct policydb *p) | |||
128 | static void cond_av_list_destroy(struct cond_av_list *list) | 128 | static void cond_av_list_destroy(struct cond_av_list *list) |
129 | { | 129 | { |
130 | struct cond_av_list *cur, *next; | 130 | struct cond_av_list *cur, *next; |
131 | for (cur = list; cur != NULL; cur = next) { | 131 | for (cur = list; cur; cur = next) { |
132 | next = cur->next; | 132 | next = cur->next; |
133 | /* the avtab_ptr_t node is destroy by the avtab */ | 133 | /* the avtab_ptr_t node is destroy by the avtab */ |
134 | kfree(cur); | 134 | kfree(cur); |
@@ -139,7 +139,7 @@ static void cond_node_destroy(struct cond_node *node) | |||
139 | { | 139 | { |
140 | struct cond_expr *cur_expr, *next_expr; | 140 | struct cond_expr *cur_expr, *next_expr; |
141 | 141 | ||
142 | for (cur_expr = node->expr; cur_expr != NULL; cur_expr = next_expr) { | 142 | for (cur_expr = node->expr; cur_expr; cur_expr = next_expr) { |
143 | next_expr = cur_expr->next; | 143 | next_expr = cur_expr->next; |
144 | kfree(cur_expr); | 144 | kfree(cur_expr); |
145 | } | 145 | } |
@@ -155,7 +155,7 @@ static void cond_list_destroy(struct cond_node *list) | |||
155 | if (list == NULL) | 155 | if (list == NULL) |
156 | return; | 156 | return; |
157 | 157 | ||
158 | for (cur = list; cur != NULL; cur = next) { | 158 | for (cur = list; cur; cur = next) { |
159 | next = cur->next; | 159 | next = cur->next; |
160 | cond_node_destroy(cur); | 160 | cond_node_destroy(cur); |
161 | } | 161 | } |
@@ -239,7 +239,7 @@ int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp) | |||
239 | rc = next_entry(key, fp, len); | 239 | rc = next_entry(key, fp, len); |
240 | if (rc < 0) | 240 | if (rc < 0) |
241 | goto err; | 241 | goto err; |
242 | key[len] = 0; | 242 | key[len] = '\0'; |
243 | if (hashtab_insert(h, key, booldatum)) | 243 | if (hashtab_insert(h, key, booldatum)) |
244 | goto err; | 244 | goto err; |
245 | 245 | ||
@@ -291,7 +291,7 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum | |||
291 | goto err; | 291 | goto err; |
292 | } | 292 | } |
293 | found = 0; | 293 | found = 0; |
294 | for (cur = other; cur != NULL; cur = cur->next) { | 294 | for (cur = other; cur; cur = cur->next) { |
295 | if (cur->node == node_ptr) { | 295 | if (cur->node == node_ptr) { |
296 | found = 1; | 296 | found = 1; |
297 | break; | 297 | break; |
@@ -485,7 +485,7 @@ void cond_compute_av(struct avtab *ctab, struct avtab_key *key, struct av_decisi | |||
485 | if (!ctab || !key || !avd) | 485 | if (!ctab || !key || !avd) |
486 | return; | 486 | return; |
487 | 487 | ||
488 | for (node = avtab_search_node(ctab, key); node != NULL; | 488 | for (node = avtab_search_node(ctab, key); node; |
489 | node = avtab_search_node_next(node, key->specified)) { | 489 | node = avtab_search_node_next(node, key->specified)) { |
490 | if ((u16)(AVTAB_ALLOWED|AVTAB_ENABLED) == | 490 | if ((u16)(AVTAB_ALLOWED|AVTAB_ENABLED) == |
491 | (node->key.specified & (AVTAB_ALLOWED|AVTAB_ENABLED))) | 491 | (node->key.specified & (AVTAB_ALLOWED|AVTAB_ENABLED))) |
diff --git a/security/selinux/ss/conditional.h b/security/selinux/ss/conditional.h index 65b9f8366e9c..53ddb013ae57 100644 --- a/security/selinux/ss/conditional.h +++ b/security/selinux/ss/conditional.h | |||
@@ -28,7 +28,7 @@ struct cond_expr { | |||
28 | #define COND_XOR 5 /* bool ^ bool */ | 28 | #define COND_XOR 5 /* bool ^ bool */ |
29 | #define COND_EQ 6 /* bool == bool */ | 29 | #define COND_EQ 6 /* bool == bool */ |
30 | #define COND_NEQ 7 /* bool != bool */ | 30 | #define COND_NEQ 7 /* bool != bool */ |
31 | #define COND_LAST 8 | 31 | #define COND_LAST COND_NEQ |
32 | __u32 expr_type; | 32 | __u32 expr_type; |
33 | __u32 bool; | 33 | __u32 bool; |
34 | struct cond_expr *next; | 34 | struct cond_expr *next; |
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c index ddc275490af8..68c7348d1acc 100644 --- a/security/selinux/ss/ebitmap.c +++ b/security/selinux/ss/ebitmap.c | |||
@@ -109,7 +109,7 @@ int ebitmap_netlbl_export(struct ebitmap *ebmap, | |||
109 | *catmap = c_iter; | 109 | *catmap = c_iter; |
110 | c_iter->startbit = e_iter->startbit & ~(NETLBL_CATMAP_SIZE - 1); | 110 | c_iter->startbit = e_iter->startbit & ~(NETLBL_CATMAP_SIZE - 1); |
111 | 111 | ||
112 | while (e_iter != NULL) { | 112 | while (e_iter) { |
113 | for (i = 0; i < EBITMAP_UNIT_NUMS; i++) { | 113 | for (i = 0; i < EBITMAP_UNIT_NUMS; i++) { |
114 | unsigned int delta, e_startbit, c_endbit; | 114 | unsigned int delta, e_startbit, c_endbit; |
115 | 115 | ||
@@ -197,7 +197,7 @@ int ebitmap_netlbl_import(struct ebitmap *ebmap, | |||
197 | } | 197 | } |
198 | } | 198 | } |
199 | c_iter = c_iter->next; | 199 | c_iter = c_iter->next; |
200 | } while (c_iter != NULL); | 200 | } while (c_iter); |
201 | if (e_iter != NULL) | 201 | if (e_iter != NULL) |
202 | ebmap->highbit = e_iter->startbit + EBITMAP_SIZE; | 202 | ebmap->highbit = e_iter->startbit + EBITMAP_SIZE; |
203 | else | 203 | else |
diff --git a/security/selinux/ss/hashtab.c b/security/selinux/ss/hashtab.c index 2e7788e13213..933e735bb185 100644 --- a/security/selinux/ss/hashtab.c +++ b/security/selinux/ss/hashtab.c | |||
@@ -81,7 +81,7 @@ void *hashtab_search(struct hashtab *h, const void *key) | |||
81 | 81 | ||
82 | hvalue = h->hash_value(h, key); | 82 | hvalue = h->hash_value(h, key); |
83 | cur = h->htable[hvalue]; | 83 | cur = h->htable[hvalue]; |
84 | while (cur != NULL && h->keycmp(h, key, cur->key) > 0) | 84 | while (cur && h->keycmp(h, key, cur->key) > 0) |
85 | cur = cur->next; | 85 | cur = cur->next; |
86 | 86 | ||
87 | if (cur == NULL || (h->keycmp(h, key, cur->key) != 0)) | 87 | if (cur == NULL || (h->keycmp(h, key, cur->key) != 0)) |
@@ -100,7 +100,7 @@ void hashtab_destroy(struct hashtab *h) | |||
100 | 100 | ||
101 | for (i = 0; i < h->size; i++) { | 101 | for (i = 0; i < h->size; i++) { |
102 | cur = h->htable[i]; | 102 | cur = h->htable[i]; |
103 | while (cur != NULL) { | 103 | while (cur) { |
104 | temp = cur; | 104 | temp = cur; |
105 | cur = cur->next; | 105 | cur = cur->next; |
106 | kfree(temp); | 106 | kfree(temp); |
@@ -127,7 +127,7 @@ int hashtab_map(struct hashtab *h, | |||
127 | 127 | ||
128 | for (i = 0; i < h->size; i++) { | 128 | for (i = 0; i < h->size; i++) { |
129 | cur = h->htable[i]; | 129 | cur = h->htable[i]; |
130 | while (cur != NULL) { | 130 | while (cur) { |
131 | ret = apply(cur->key, cur->datum, args); | 131 | ret = apply(cur->key, cur->datum, args); |
132 | if (ret) | 132 | if (ret) |
133 | return ret; | 133 | return ret; |
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c index 77d745da48bb..b5407f16c2a4 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c | |||
@@ -283,8 +283,8 @@ int mls_context_to_sid(struct policydb *pol, | |||
283 | p++; | 283 | p++; |
284 | 284 | ||
285 | delim = *p; | 285 | delim = *p; |
286 | if (delim != 0) | 286 | if (delim != '\0') |
287 | *p++ = 0; | 287 | *p++ = '\0'; |
288 | 288 | ||
289 | for (l = 0; l < 2; l++) { | 289 | for (l = 0; l < 2; l++) { |
290 | levdatum = hashtab_search(pol->p_levels.table, scontextp); | 290 | levdatum = hashtab_search(pol->p_levels.table, scontextp); |
@@ -302,14 +302,14 @@ int mls_context_to_sid(struct policydb *pol, | |||
302 | while (*p && *p != ',' && *p != '-') | 302 | while (*p && *p != ',' && *p != '-') |
303 | p++; | 303 | p++; |
304 | delim = *p; | 304 | delim = *p; |
305 | if (delim != 0) | 305 | if (delim != '\0') |
306 | *p++ = 0; | 306 | *p++ = '\0'; |
307 | 307 | ||
308 | /* Separate into range if exists */ | 308 | /* Separate into range if exists */ |
309 | rngptr = strchr(scontextp, '.'); | 309 | rngptr = strchr(scontextp, '.'); |
310 | if (rngptr != NULL) { | 310 | if (rngptr != NULL) { |
311 | /* Remove '.' */ | 311 | /* Remove '.' */ |
312 | *rngptr++ = 0; | 312 | *rngptr++ = '\0'; |
313 | } | 313 | } |
314 | 314 | ||
315 | catdatum = hashtab_search(pol->p_cats.table, | 315 | catdatum = hashtab_search(pol->p_cats.table, |
@@ -357,8 +357,8 @@ int mls_context_to_sid(struct policydb *pol, | |||
357 | p++; | 357 | p++; |
358 | 358 | ||
359 | delim = *p; | 359 | delim = *p; |
360 | if (delim != 0) | 360 | if (delim != '\0') |
361 | *p++ = 0; | 361 | *p++ = '\0'; |
362 | } else | 362 | } else |
363 | break; | 363 | break; |
364 | } | 364 | } |
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index 2391761ae422..26646305dc0e 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c | |||
@@ -932,7 +932,7 @@ static int perm_read(struct policydb *p, struct hashtab *h, void *fp) | |||
932 | rc = next_entry(key, fp, len); | 932 | rc = next_entry(key, fp, len); |
933 | if (rc < 0) | 933 | if (rc < 0) |
934 | goto bad; | 934 | goto bad; |
935 | key[len] = 0; | 935 | key[len] = '\0'; |
936 | 936 | ||
937 | rc = hashtab_insert(h, key, perdatum); | 937 | rc = hashtab_insert(h, key, perdatum); |
938 | if (rc) | 938 | if (rc) |
@@ -979,7 +979,7 @@ static int common_read(struct policydb *p, struct hashtab *h, void *fp) | |||
979 | rc = next_entry(key, fp, len); | 979 | rc = next_entry(key, fp, len); |
980 | if (rc < 0) | 980 | if (rc < 0) |
981 | goto bad; | 981 | goto bad; |
982 | key[len] = 0; | 982 | key[len] = '\0'; |
983 | 983 | ||
984 | for (i = 0; i < nel; i++) { | 984 | for (i = 0; i < nel; i++) { |
985 | rc = perm_read(p, comdatum->permissions.table, fp); | 985 | rc = perm_read(p, comdatum->permissions.table, fp); |
@@ -1117,7 +1117,7 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp) | |||
1117 | rc = next_entry(key, fp, len); | 1117 | rc = next_entry(key, fp, len); |
1118 | if (rc < 0) | 1118 | if (rc < 0) |
1119 | goto bad; | 1119 | goto bad; |
1120 | key[len] = 0; | 1120 | key[len] = '\0'; |
1121 | 1121 | ||
1122 | if (len2) { | 1122 | if (len2) { |
1123 | cladatum->comkey = kmalloc(len2 + 1, GFP_KERNEL); | 1123 | cladatum->comkey = kmalloc(len2 + 1, GFP_KERNEL); |
@@ -1128,7 +1128,7 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp) | |||
1128 | rc = next_entry(cladatum->comkey, fp, len2); | 1128 | rc = next_entry(cladatum->comkey, fp, len2); |
1129 | if (rc < 0) | 1129 | if (rc < 0) |
1130 | goto bad; | 1130 | goto bad; |
1131 | cladatum->comkey[len2] = 0; | 1131 | cladatum->comkey[len2] = '\0'; |
1132 | 1132 | ||
1133 | cladatum->comdatum = hashtab_search(p->p_commons.table, | 1133 | cladatum->comdatum = hashtab_search(p->p_commons.table, |
1134 | cladatum->comkey); | 1134 | cladatum->comkey); |
@@ -1201,7 +1201,7 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp) | |||
1201 | rc = next_entry(key, fp, len); | 1201 | rc = next_entry(key, fp, len); |
1202 | if (rc < 0) | 1202 | if (rc < 0) |
1203 | goto bad; | 1203 | goto bad; |
1204 | key[len] = 0; | 1204 | key[len] = '\0'; |
1205 | 1205 | ||
1206 | rc = ebitmap_read(&role->dominates, fp); | 1206 | rc = ebitmap_read(&role->dominates, fp); |
1207 | if (rc) | 1207 | if (rc) |
@@ -1262,7 +1262,7 @@ static int type_read(struct policydb *p, struct hashtab *h, void *fp) | |||
1262 | rc = next_entry(key, fp, len); | 1262 | rc = next_entry(key, fp, len); |
1263 | if (rc < 0) | 1263 | if (rc < 0) |
1264 | goto bad; | 1264 | goto bad; |
1265 | key[len] = 0; | 1265 | key[len] = '\0'; |
1266 | 1266 | ||
1267 | rc = hashtab_insert(h, key, typdatum); | 1267 | rc = hashtab_insert(h, key, typdatum); |
1268 | if (rc) | 1268 | if (rc) |
@@ -1334,7 +1334,7 @@ static int user_read(struct policydb *p, struct hashtab *h, void *fp) | |||
1334 | rc = next_entry(key, fp, len); | 1334 | rc = next_entry(key, fp, len); |
1335 | if (rc < 0) | 1335 | if (rc < 0) |
1336 | goto bad; | 1336 | goto bad; |
1337 | key[len] = 0; | 1337 | key[len] = '\0'; |
1338 | 1338 | ||
1339 | rc = ebitmap_read(&usrdatum->roles, fp); | 1339 | rc = ebitmap_read(&usrdatum->roles, fp); |
1340 | if (rc) | 1340 | if (rc) |
@@ -1388,7 +1388,7 @@ static int sens_read(struct policydb *p, struct hashtab *h, void *fp) | |||
1388 | rc = next_entry(key, fp, len); | 1388 | rc = next_entry(key, fp, len); |
1389 | if (rc < 0) | 1389 | if (rc < 0) |
1390 | goto bad; | 1390 | goto bad; |
1391 | key[len] = 0; | 1391 | key[len] = '\0'; |
1392 | 1392 | ||
1393 | levdatum->level = kmalloc(sizeof(struct mls_level), GFP_ATOMIC); | 1393 | levdatum->level = kmalloc(sizeof(struct mls_level), GFP_ATOMIC); |
1394 | if (!levdatum->level) { | 1394 | if (!levdatum->level) { |
@@ -1440,7 +1440,7 @@ static int cat_read(struct policydb *p, struct hashtab *h, void *fp) | |||
1440 | rc = next_entry(key, fp, len); | 1440 | rc = next_entry(key, fp, len); |
1441 | if (rc < 0) | 1441 | if (rc < 0) |
1442 | goto bad; | 1442 | goto bad; |
1443 | key[len] = 0; | 1443 | key[len] = '\0'; |
1444 | 1444 | ||
1445 | rc = hashtab_insert(h, key, catdatum); | 1445 | rc = hashtab_insert(h, key, catdatum); |
1446 | if (rc) | 1446 | if (rc) |
@@ -1523,7 +1523,7 @@ int policydb_read(struct policydb *p, void *fp) | |||
1523 | kfree(policydb_str); | 1523 | kfree(policydb_str); |
1524 | goto bad; | 1524 | goto bad; |
1525 | } | 1525 | } |
1526 | policydb_str[len] = 0; | 1526 | policydb_str[len] = '\0'; |
1527 | if (strcmp(policydb_str, POLICYDB_STRING)) { | 1527 | if (strcmp(policydb_str, POLICYDB_STRING)) { |
1528 | printk(KERN_ERR "SELinux: policydb string %s does not match " | 1528 | printk(KERN_ERR "SELinux: policydb string %s does not match " |
1529 | "my string %s\n", policydb_str, POLICYDB_STRING); | 1529 | "my string %s\n", policydb_str, POLICYDB_STRING); |
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index b52f923ce680..5a0536bddc63 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
@@ -356,7 +356,7 @@ static int context_struct_compute_av(struct context *scontext, | |||
356 | avkey.source_type = i + 1; | 356 | avkey.source_type = i + 1; |
357 | avkey.target_type = j + 1; | 357 | avkey.target_type = j + 1; |
358 | for (node = avtab_search_node(&policydb.te_avtab, &avkey); | 358 | for (node = avtab_search_node(&policydb.te_avtab, &avkey); |
359 | node != NULL; | 359 | node; |
360 | node = avtab_search_node_next(node, avkey.specified)) { | 360 | node = avtab_search_node_next(node, avkey.specified)) { |
361 | if (node->key.specified == AVTAB_ALLOWED) | 361 | if (node->key.specified == AVTAB_ALLOWED) |
362 | avd->allowed |= node->datum.data; | 362 | avd->allowed |= node->datum.data; |
@@ -1037,7 +1037,7 @@ static int security_compute_sid(u32 ssid, | |||
1037 | /* If no permanent rule, also check for enabled conditional rules */ | 1037 | /* If no permanent rule, also check for enabled conditional rules */ |
1038 | if (!avdatum) { | 1038 | if (!avdatum) { |
1039 | node = avtab_search_node(&policydb.te_cond_avtab, &avkey); | 1039 | node = avtab_search_node(&policydb.te_cond_avtab, &avkey); |
1040 | for (; node != NULL; node = avtab_search_node_next(node, specified)) { | 1040 | for (; node; node = avtab_search_node_next(node, specified)) { |
1041 | if (node->key.specified & AVTAB_ENABLED) { | 1041 | if (node->key.specified & AVTAB_ENABLED) { |
1042 | avdatum = &node->datum; | 1042 | avdatum = &node->datum; |
1043 | break; | 1043 | break; |
@@ -2050,7 +2050,7 @@ int security_set_bools(int len, int *values) | |||
2050 | policydb.bool_val_to_struct[i]->state = 0; | 2050 | policydb.bool_val_to_struct[i]->state = 0; |
2051 | } | 2051 | } |
2052 | 2052 | ||
2053 | for (cur = policydb.cond_list; cur != NULL; cur = cur->next) { | 2053 | for (cur = policydb.cond_list; cur; cur = cur->next) { |
2054 | rc = evaluate_cond_node(&policydb, cur); | 2054 | rc = evaluate_cond_node(&policydb, cur); |
2055 | if (rc) | 2055 | if (rc) |
2056 | goto out; | 2056 | goto out; |
@@ -2102,7 +2102,7 @@ static int security_preserve_bools(struct policydb *p) | |||
2102 | if (booldatum) | 2102 | if (booldatum) |
2103 | booldatum->state = bvalues[i]; | 2103 | booldatum->state = bvalues[i]; |
2104 | } | 2104 | } |
2105 | for (cur = p->cond_list; cur != NULL; cur = cur->next) { | 2105 | for (cur = p->cond_list; cur; cur = cur->next) { |
2106 | rc = evaluate_cond_node(p, cur); | 2106 | rc = evaluate_cond_node(p, cur); |
2107 | if (rc) | 2107 | if (rc) |
2108 | goto out; | 2108 | goto out; |
diff --git a/security/selinux/ss/sidtab.c b/security/selinux/ss/sidtab.c index a81ded104129..e817989764cd 100644 --- a/security/selinux/ss/sidtab.c +++ b/security/selinux/ss/sidtab.c | |||
@@ -43,7 +43,7 @@ int sidtab_insert(struct sidtab *s, u32 sid, struct context *context) | |||
43 | hvalue = SIDTAB_HASH(sid); | 43 | hvalue = SIDTAB_HASH(sid); |
44 | prev = NULL; | 44 | prev = NULL; |
45 | cur = s->htable[hvalue]; | 45 | cur = s->htable[hvalue]; |
46 | while (cur != NULL && sid > cur->sid) { | 46 | while (cur && sid > cur->sid) { |
47 | prev = cur; | 47 | prev = cur; |
48 | cur = cur->next; | 48 | cur = cur->next; |
49 | } | 49 | } |
@@ -92,7 +92,7 @@ static struct context *sidtab_search_core(struct sidtab *s, u32 sid, int force) | |||
92 | 92 | ||
93 | hvalue = SIDTAB_HASH(sid); | 93 | hvalue = SIDTAB_HASH(sid); |
94 | cur = s->htable[hvalue]; | 94 | cur = s->htable[hvalue]; |
95 | while (cur != NULL && sid > cur->sid) | 95 | while (cur && sid > cur->sid) |
96 | cur = cur->next; | 96 | cur = cur->next; |
97 | 97 | ||
98 | if (force && cur && sid == cur->sid && cur->context.len) | 98 | if (force && cur && sid == cur->sid && cur->context.len) |
@@ -103,7 +103,7 @@ static struct context *sidtab_search_core(struct sidtab *s, u32 sid, int force) | |||
103 | sid = SECINITSID_UNLABELED; | 103 | sid = SECINITSID_UNLABELED; |
104 | hvalue = SIDTAB_HASH(sid); | 104 | hvalue = SIDTAB_HASH(sid); |
105 | cur = s->htable[hvalue]; | 105 | cur = s->htable[hvalue]; |
106 | while (cur != NULL && sid > cur->sid) | 106 | while (cur && sid > cur->sid) |
107 | cur = cur->next; | 107 | cur = cur->next; |
108 | if (!cur || sid != cur->sid) | 108 | if (!cur || sid != cur->sid) |
109 | return NULL; | 109 | return NULL; |
@@ -136,7 +136,7 @@ int sidtab_map(struct sidtab *s, | |||
136 | 136 | ||
137 | for (i = 0; i < SIDTAB_SIZE; i++) { | 137 | for (i = 0; i < SIDTAB_SIZE; i++) { |
138 | cur = s->htable[i]; | 138 | cur = s->htable[i]; |
139 | while (cur != NULL) { | 139 | while (cur) { |
140 | rc = apply(cur->sid, &cur->context, args); | 140 | rc = apply(cur->sid, &cur->context, args); |
141 | if (rc) | 141 | if (rc) |
142 | goto out; | 142 | goto out; |
@@ -155,7 +155,7 @@ static inline u32 sidtab_search_context(struct sidtab *s, | |||
155 | 155 | ||
156 | for (i = 0; i < SIDTAB_SIZE; i++) { | 156 | for (i = 0; i < SIDTAB_SIZE; i++) { |
157 | cur = s->htable[i]; | 157 | cur = s->htable[i]; |
158 | while (cur != NULL) { | 158 | while (cur) { |
159 | if (context_cmp(&cur->context, context)) | 159 | if (context_cmp(&cur->context, context)) |
160 | return cur->sid; | 160 | return cur->sid; |
161 | cur = cur->next; | 161 | cur = cur->next; |
@@ -242,7 +242,7 @@ void sidtab_destroy(struct sidtab *s) | |||
242 | 242 | ||
243 | for (i = 0; i < SIDTAB_SIZE; i++) { | 243 | for (i = 0; i < SIDTAB_SIZE; i++) { |
244 | cur = s->htable[i]; | 244 | cur = s->htable[i]; |
245 | while (cur != NULL) { | 245 | while (cur) { |
246 | temp = cur; | 246 | temp = cur; |
247 | cur = cur->next; | 247 | cur = cur->next; |
248 | context_destroy(&temp->context); | 248 | context_destroy(&temp->context); |
diff --git a/security/smack/smack.h b/security/smack/smack.h index 4a4477f5afdc..31dce559595a 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h | |||
@@ -178,6 +178,7 @@ u32 smack_to_secid(const char *); | |||
178 | extern int smack_cipso_direct; | 178 | extern int smack_cipso_direct; |
179 | extern int smack_net_nltype; | 179 | extern int smack_net_nltype; |
180 | extern char *smack_net_ambient; | 180 | extern char *smack_net_ambient; |
181 | extern char *smack_onlycap; | ||
181 | 182 | ||
182 | extern struct smack_known *smack_known; | 183 | extern struct smack_known *smack_known; |
183 | extern struct smack_known smack_known_floor; | 184 | extern struct smack_known smack_known_floor; |
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c index f6b5f6eed6dd..79ff21ed4c3b 100644 --- a/security/smack/smack_access.c +++ b/security/smack/smack_access.c | |||
@@ -157,7 +157,7 @@ int smk_access(char *subject_label, char *object_label, int request) | |||
157 | * | 157 | * |
158 | * This function checks the current subject label/object label pair | 158 | * This function checks the current subject label/object label pair |
159 | * in the access rule list and returns 0 if the access is permitted, | 159 | * in the access rule list and returns 0 if the access is permitted, |
160 | * non zero otherwise. It allows that current my have the capability | 160 | * non zero otherwise. It allows that current may have the capability |
161 | * to override the rules. | 161 | * to override the rules. |
162 | */ | 162 | */ |
163 | int smk_curacc(char *obj_label, u32 mode) | 163 | int smk_curacc(char *obj_label, u32 mode) |
@@ -168,6 +168,14 @@ int smk_curacc(char *obj_label, u32 mode) | |||
168 | if (rc == 0) | 168 | if (rc == 0) |
169 | return 0; | 169 | return 0; |
170 | 170 | ||
171 | /* | ||
172 | * Return if a specific label has been designated as the | ||
173 | * only one that gets privilege and current does not | ||
174 | * have that label. | ||
175 | */ | ||
176 | if (smack_onlycap != NULL && smack_onlycap != current->security) | ||
177 | return rc; | ||
178 | |||
171 | if (capable(CAP_MAC_OVERRIDE)) | 179 | if (capable(CAP_MAC_OVERRIDE)) |
172 | return 0; | 180 | return 0; |
173 | 181 | ||
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index 271a835fbbe3..e7c642458ec9 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c | |||
@@ -39,6 +39,7 @@ enum smk_inos { | |||
39 | SMK_DIRECT = 6, /* CIPSO level indicating direct label */ | 39 | SMK_DIRECT = 6, /* CIPSO level indicating direct label */ |
40 | SMK_AMBIENT = 7, /* internet ambient label */ | 40 | SMK_AMBIENT = 7, /* internet ambient label */ |
41 | SMK_NLTYPE = 8, /* label scheme to use by default */ | 41 | SMK_NLTYPE = 8, /* label scheme to use by default */ |
42 | SMK_ONLYCAP = 9, /* the only "capable" label */ | ||
42 | }; | 43 | }; |
43 | 44 | ||
44 | /* | 45 | /* |
@@ -68,6 +69,16 @@ int smack_net_nltype = NETLBL_NLTYPE_CIPSOV4; | |||
68 | */ | 69 | */ |
69 | int smack_cipso_direct = SMACK_CIPSO_DIRECT_DEFAULT; | 70 | int smack_cipso_direct = SMACK_CIPSO_DIRECT_DEFAULT; |
70 | 71 | ||
72 | /* | ||
73 | * Unless a process is running with this label even | ||
74 | * having CAP_MAC_OVERRIDE isn't enough to grant | ||
75 | * privilege to violate MAC policy. If no label is | ||
76 | * designated (the NULL case) capabilities apply to | ||
77 | * everyone. It is expected that the hat (^) label | ||
78 | * will be used if any label is used. | ||
79 | */ | ||
80 | char *smack_onlycap; | ||
81 | |||
71 | static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT; | 82 | static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT; |
72 | struct smk_list_entry *smack_list; | 83 | struct smk_list_entry *smack_list; |
73 | 84 | ||
@@ -787,6 +798,85 @@ static const struct file_operations smk_ambient_ops = { | |||
787 | .write = smk_write_ambient, | 798 | .write = smk_write_ambient, |
788 | }; | 799 | }; |
789 | 800 | ||
801 | /** | ||
802 | * smk_read_onlycap - read() for /smack/onlycap | ||
803 | * @filp: file pointer, not actually used | ||
804 | * @buf: where to put the result | ||
805 | * @cn: maximum to send along | ||
806 | * @ppos: where to start | ||
807 | * | ||
808 | * Returns number of bytes read or error code, as appropriate | ||
809 | */ | ||
810 | static ssize_t smk_read_onlycap(struct file *filp, char __user *buf, | ||
811 | size_t cn, loff_t *ppos) | ||
812 | { | ||
813 | char *smack = ""; | ||
814 | ssize_t rc = -EINVAL; | ||
815 | int asize; | ||
816 | |||
817 | if (*ppos != 0) | ||
818 | return 0; | ||
819 | |||
820 | if (smack_onlycap != NULL) | ||
821 | smack = smack_onlycap; | ||
822 | |||
823 | asize = strlen(smack) + 1; | ||
824 | |||
825 | if (cn >= asize) | ||
826 | rc = simple_read_from_buffer(buf, cn, ppos, smack, asize); | ||
827 | |||
828 | return rc; | ||
829 | } | ||
830 | |||
831 | /** | ||
832 | * smk_write_onlycap - write() for /smack/onlycap | ||
833 | * @filp: file pointer, not actually used | ||
834 | * @buf: where to get the data from | ||
835 | * @count: bytes sent | ||
836 | * @ppos: where to start | ||
837 | * | ||
838 | * Returns number of bytes written or error code, as appropriate | ||
839 | */ | ||
840 | static ssize_t smk_write_onlycap(struct file *file, const char __user *buf, | ||
841 | size_t count, loff_t *ppos) | ||
842 | { | ||
843 | char in[SMK_LABELLEN]; | ||
844 | char *sp = current->security; | ||
845 | |||
846 | if (!capable(CAP_MAC_ADMIN)) | ||
847 | return -EPERM; | ||
848 | |||
849 | /* | ||
850 | * This can be done using smk_access() but is done | ||
851 | * explicitly for clarity. The smk_access() implementation | ||
852 | * would use smk_access(smack_onlycap, MAY_WRITE) | ||
853 | */ | ||
854 | if (smack_onlycap != NULL && smack_onlycap != sp) | ||
855 | return -EPERM; | ||
856 | |||
857 | if (count >= SMK_LABELLEN) | ||
858 | return -EINVAL; | ||
859 | |||
860 | if (copy_from_user(in, buf, count) != 0) | ||
861 | return -EFAULT; | ||
862 | |||
863 | /* | ||
864 | * Should the null string be passed in unset the onlycap value. | ||
865 | * This seems like something to be careful with as usually | ||
866 | * smk_import only expects to return NULL for errors. It | ||
867 | * is usually the case that a nullstring or "\n" would be | ||
868 | * bad to pass to smk_import but in fact this is useful here. | ||
869 | */ | ||
870 | smack_onlycap = smk_import(in, count); | ||
871 | |||
872 | return count; | ||
873 | } | ||
874 | |||
875 | static const struct file_operations smk_onlycap_ops = { | ||
876 | .read = smk_read_onlycap, | ||
877 | .write = smk_write_onlycap, | ||
878 | }; | ||
879 | |||
790 | struct option_names { | 880 | struct option_names { |
791 | int o_number; | 881 | int o_number; |
792 | char *o_name; | 882 | char *o_name; |
@@ -919,6 +1009,8 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent) | |||
919 | {"ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR}, | 1009 | {"ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR}, |
920 | [SMK_NLTYPE] = | 1010 | [SMK_NLTYPE] = |
921 | {"nltype", &smk_nltype_ops, S_IRUGO|S_IWUSR}, | 1011 | {"nltype", &smk_nltype_ops, S_IRUGO|S_IWUSR}, |
1012 | [SMK_ONLYCAP] = | ||
1013 | {"onlycap", &smk_onlycap_ops, S_IRUGO|S_IWUSR}, | ||
922 | /* last one */ {""} | 1014 | /* last one */ {""} |
923 | }; | 1015 | }; |
924 | 1016 | ||