Commit 4bc87e62775052aac0be7574d5f84ff06f61c6b4
Committed by
Linus Torvalds
1 parent
9a4c8546f3
Exists in
master
and in
7 other branches
Smack: unlabeled outgoing ambient packets
Smack uses CIPSO labeling, but allows for unlabeled packets by specifying an "ambient" label that is applied to incoming unlabeled packets. Because the other end of the connection may dislike IP options, and ssh is one know application that behaves thus, it is prudent to respond in kind. This patch changes the network labeling behavior such that an outgoing packet that would be given a CIPSO label that matches the ambient label is left unlabeled. An "unlbl" domain is added and the netlabel defaulting mechanism invoked rather than assuming that everything is CIPSO. Locking has been added around changes to the ambient label as the mechanisms used to do so are more involved. Signed-off-by: Casey Schaufler <casey@schaufler-ca.com> Acked-by: Paul Moore <paul.moore@hp.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 2 changed files with 74 additions and 23 deletions Inline Diff
security/smack/smack_lsm.c
1 | /* | 1 | /* |
2 | * Simplified MAC Kernel (smack) security module | 2 | * Simplified MAC Kernel (smack) security module |
3 | * | 3 | * |
4 | * This file contains the smack hook function implementations. | 4 | * This file contains the smack hook function implementations. |
5 | * | 5 | * |
6 | * Author: | 6 | * Author: |
7 | * Casey Schaufler <casey@schaufler-ca.com> | 7 | * Casey Schaufler <casey@schaufler-ca.com> |
8 | * | 8 | * |
9 | * Copyright (C) 2007 Casey Schaufler <casey@schaufler-ca.com> | 9 | * Copyright (C) 2007 Casey Schaufler <casey@schaufler-ca.com> |
10 | * | 10 | * |
11 | * This program is free software; you can redistribute it and/or modify | 11 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of the GNU General Public License version 2, | 12 | * it under the terms of the GNU General Public License version 2, |
13 | * as published by the Free Software Foundation. | 13 | * as published by the Free Software Foundation. |
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/xattr.h> | 16 | #include <linux/xattr.h> |
17 | #include <linux/pagemap.h> | 17 | #include <linux/pagemap.h> |
18 | #include <linux/mount.h> | 18 | #include <linux/mount.h> |
19 | #include <linux/stat.h> | 19 | #include <linux/stat.h> |
20 | #include <linux/ext2_fs.h> | 20 | #include <linux/ext2_fs.h> |
21 | #include <linux/kd.h> | 21 | #include <linux/kd.h> |
22 | #include <asm/ioctls.h> | 22 | #include <asm/ioctls.h> |
23 | #include <linux/tcp.h> | 23 | #include <linux/tcp.h> |
24 | #include <linux/udp.h> | 24 | #include <linux/udp.h> |
25 | #include <linux/mutex.h> | 25 | #include <linux/mutex.h> |
26 | #include <linux/pipe_fs_i.h> | 26 | #include <linux/pipe_fs_i.h> |
27 | #include <net/netlabel.h> | 27 | #include <net/netlabel.h> |
28 | #include <net/cipso_ipv4.h> | 28 | #include <net/cipso_ipv4.h> |
29 | 29 | ||
30 | #include "smack.h" | 30 | #include "smack.h" |
31 | 31 | ||
32 | /* | 32 | /* |
33 | * I hope these are the hokeyist lines of code in the module. Casey. | 33 | * I hope these are the hokeyist lines of code in the module. Casey. |
34 | */ | 34 | */ |
35 | #define DEVPTS_SUPER_MAGIC 0x1cd1 | 35 | #define DEVPTS_SUPER_MAGIC 0x1cd1 |
36 | #define SOCKFS_MAGIC 0x534F434B | 36 | #define SOCKFS_MAGIC 0x534F434B |
37 | #define TMPFS_MAGIC 0x01021994 | 37 | #define TMPFS_MAGIC 0x01021994 |
38 | 38 | ||
39 | /** | 39 | /** |
40 | * smk_fetch - Fetch the smack label from a file. | 40 | * smk_fetch - Fetch the smack label from a file. |
41 | * @ip: a pointer to the inode | 41 | * @ip: a pointer to the inode |
42 | * @dp: a pointer to the dentry | 42 | * @dp: a pointer to the dentry |
43 | * | 43 | * |
44 | * Returns a pointer to the master list entry for the Smack label | 44 | * Returns a pointer to the master list entry for the Smack label |
45 | * or NULL if there was no label to fetch. | 45 | * or NULL if there was no label to fetch. |
46 | */ | 46 | */ |
47 | static char *smk_fetch(struct inode *ip, struct dentry *dp) | 47 | static char *smk_fetch(struct inode *ip, struct dentry *dp) |
48 | { | 48 | { |
49 | int rc; | 49 | int rc; |
50 | char in[SMK_LABELLEN]; | 50 | char in[SMK_LABELLEN]; |
51 | 51 | ||
52 | if (ip->i_op->getxattr == NULL) | 52 | if (ip->i_op->getxattr == NULL) |
53 | return NULL; | 53 | return NULL; |
54 | 54 | ||
55 | rc = ip->i_op->getxattr(dp, XATTR_NAME_SMACK, in, SMK_LABELLEN); | 55 | rc = ip->i_op->getxattr(dp, XATTR_NAME_SMACK, in, SMK_LABELLEN); |
56 | if (rc < 0) | 56 | if (rc < 0) |
57 | return NULL; | 57 | return NULL; |
58 | 58 | ||
59 | return smk_import(in, rc); | 59 | return smk_import(in, rc); |
60 | } | 60 | } |
61 | 61 | ||
62 | /** | 62 | /** |
63 | * new_inode_smack - allocate an inode security blob | 63 | * new_inode_smack - allocate an inode security blob |
64 | * @smack: a pointer to the Smack label to use in the blob | 64 | * @smack: a pointer to the Smack label to use in the blob |
65 | * | 65 | * |
66 | * Returns the new blob or NULL if there's no memory available | 66 | * Returns the new blob or NULL if there's no memory available |
67 | */ | 67 | */ |
68 | struct inode_smack *new_inode_smack(char *smack) | 68 | struct inode_smack *new_inode_smack(char *smack) |
69 | { | 69 | { |
70 | struct inode_smack *isp; | 70 | struct inode_smack *isp; |
71 | 71 | ||
72 | isp = kzalloc(sizeof(struct inode_smack), GFP_KERNEL); | 72 | isp = kzalloc(sizeof(struct inode_smack), GFP_KERNEL); |
73 | if (isp == NULL) | 73 | if (isp == NULL) |
74 | return NULL; | 74 | return NULL; |
75 | 75 | ||
76 | isp->smk_inode = smack; | 76 | isp->smk_inode = smack; |
77 | isp->smk_flags = 0; | 77 | isp->smk_flags = 0; |
78 | mutex_init(&isp->smk_lock); | 78 | mutex_init(&isp->smk_lock); |
79 | 79 | ||
80 | return isp; | 80 | return isp; |
81 | } | 81 | } |
82 | 82 | ||
83 | /* | 83 | /* |
84 | * LSM hooks. | 84 | * LSM hooks. |
85 | * We he, that is fun! | 85 | * We he, that is fun! |
86 | */ | 86 | */ |
87 | 87 | ||
88 | /** | 88 | /** |
89 | * smack_ptrace - Smack approval on ptrace | 89 | * smack_ptrace - Smack approval on ptrace |
90 | * @ptp: parent task pointer | 90 | * @ptp: parent task pointer |
91 | * @ctp: child task pointer | 91 | * @ctp: child task pointer |
92 | * | 92 | * |
93 | * Returns 0 if access is OK, an error code otherwise | 93 | * Returns 0 if access is OK, an error code otherwise |
94 | * | 94 | * |
95 | * Do the capability checks, and require read and write. | 95 | * Do the capability checks, and require read and write. |
96 | */ | 96 | */ |
97 | static int smack_ptrace(struct task_struct *ptp, struct task_struct *ctp) | 97 | static int smack_ptrace(struct task_struct *ptp, struct task_struct *ctp) |
98 | { | 98 | { |
99 | int rc; | 99 | int rc; |
100 | 100 | ||
101 | rc = cap_ptrace(ptp, ctp); | 101 | rc = cap_ptrace(ptp, ctp); |
102 | if (rc != 0) | 102 | if (rc != 0) |
103 | return rc; | 103 | return rc; |
104 | 104 | ||
105 | rc = smk_access(ptp->security, ctp->security, MAY_READWRITE); | 105 | rc = smk_access(ptp->security, ctp->security, MAY_READWRITE); |
106 | if (rc != 0 && __capable(ptp, CAP_MAC_OVERRIDE)) | 106 | if (rc != 0 && __capable(ptp, CAP_MAC_OVERRIDE)) |
107 | return 0; | 107 | return 0; |
108 | 108 | ||
109 | return rc; | 109 | return rc; |
110 | } | 110 | } |
111 | 111 | ||
112 | /** | 112 | /** |
113 | * smack_syslog - Smack approval on syslog | 113 | * smack_syslog - Smack approval on syslog |
114 | * @type: message type | 114 | * @type: message type |
115 | * | 115 | * |
116 | * Require that the task has the floor label | 116 | * Require that the task has the floor label |
117 | * | 117 | * |
118 | * Returns 0 on success, error code otherwise. | 118 | * Returns 0 on success, error code otherwise. |
119 | */ | 119 | */ |
120 | static int smack_syslog(int type) | 120 | static int smack_syslog(int type) |
121 | { | 121 | { |
122 | int rc; | 122 | int rc; |
123 | char *sp = current->security; | 123 | char *sp = current->security; |
124 | 124 | ||
125 | rc = cap_syslog(type); | 125 | rc = cap_syslog(type); |
126 | if (rc != 0) | 126 | if (rc != 0) |
127 | return rc; | 127 | return rc; |
128 | 128 | ||
129 | if (capable(CAP_MAC_OVERRIDE)) | 129 | if (capable(CAP_MAC_OVERRIDE)) |
130 | return 0; | 130 | return 0; |
131 | 131 | ||
132 | if (sp != smack_known_floor.smk_known) | 132 | if (sp != smack_known_floor.smk_known) |
133 | rc = -EACCES; | 133 | rc = -EACCES; |
134 | 134 | ||
135 | return rc; | 135 | return rc; |
136 | } | 136 | } |
137 | 137 | ||
138 | 138 | ||
139 | /* | 139 | /* |
140 | * Superblock Hooks. | 140 | * Superblock Hooks. |
141 | */ | 141 | */ |
142 | 142 | ||
143 | /** | 143 | /** |
144 | * smack_sb_alloc_security - allocate a superblock blob | 144 | * smack_sb_alloc_security - allocate a superblock blob |
145 | * @sb: the superblock getting the blob | 145 | * @sb: the superblock getting the blob |
146 | * | 146 | * |
147 | * Returns 0 on success or -ENOMEM on error. | 147 | * Returns 0 on success or -ENOMEM on error. |
148 | */ | 148 | */ |
149 | static int smack_sb_alloc_security(struct super_block *sb) | 149 | static int smack_sb_alloc_security(struct super_block *sb) |
150 | { | 150 | { |
151 | struct superblock_smack *sbsp; | 151 | struct superblock_smack *sbsp; |
152 | 152 | ||
153 | sbsp = kzalloc(sizeof(struct superblock_smack), GFP_KERNEL); | 153 | sbsp = kzalloc(sizeof(struct superblock_smack), GFP_KERNEL); |
154 | 154 | ||
155 | if (sbsp == NULL) | 155 | if (sbsp == NULL) |
156 | return -ENOMEM; | 156 | return -ENOMEM; |
157 | 157 | ||
158 | sbsp->smk_root = smack_known_floor.smk_known; | 158 | sbsp->smk_root = smack_known_floor.smk_known; |
159 | sbsp->smk_default = smack_known_floor.smk_known; | 159 | sbsp->smk_default = smack_known_floor.smk_known; |
160 | sbsp->smk_floor = smack_known_floor.smk_known; | 160 | sbsp->smk_floor = smack_known_floor.smk_known; |
161 | sbsp->smk_hat = smack_known_hat.smk_known; | 161 | sbsp->smk_hat = smack_known_hat.smk_known; |
162 | sbsp->smk_initialized = 0; | 162 | sbsp->smk_initialized = 0; |
163 | spin_lock_init(&sbsp->smk_sblock); | 163 | spin_lock_init(&sbsp->smk_sblock); |
164 | 164 | ||
165 | sb->s_security = sbsp; | 165 | sb->s_security = sbsp; |
166 | 166 | ||
167 | return 0; | 167 | return 0; |
168 | } | 168 | } |
169 | 169 | ||
170 | /** | 170 | /** |
171 | * smack_sb_free_security - free a superblock blob | 171 | * smack_sb_free_security - free a superblock blob |
172 | * @sb: the superblock getting the blob | 172 | * @sb: the superblock getting the blob |
173 | * | 173 | * |
174 | */ | 174 | */ |
175 | static void smack_sb_free_security(struct super_block *sb) | 175 | static void smack_sb_free_security(struct super_block *sb) |
176 | { | 176 | { |
177 | kfree(sb->s_security); | 177 | kfree(sb->s_security); |
178 | sb->s_security = NULL; | 178 | sb->s_security = NULL; |
179 | } | 179 | } |
180 | 180 | ||
181 | /** | 181 | /** |
182 | * smack_sb_copy_data - copy mount options data for processing | 182 | * smack_sb_copy_data - copy mount options data for processing |
183 | * @type: file system type | 183 | * @type: file system type |
184 | * @orig: where to start | 184 | * @orig: where to start |
185 | * @smackopts | 185 | * @smackopts |
186 | * | 186 | * |
187 | * Returns 0 on success or -ENOMEM on error. | 187 | * Returns 0 on success or -ENOMEM on error. |
188 | * | 188 | * |
189 | * Copy the Smack specific mount options out of the mount | 189 | * Copy the Smack specific mount options out of the mount |
190 | * options list. | 190 | * options list. |
191 | */ | 191 | */ |
192 | static int smack_sb_copy_data(struct file_system_type *type, void *orig, | 192 | static int smack_sb_copy_data(struct file_system_type *type, void *orig, |
193 | void *smackopts) | 193 | void *smackopts) |
194 | { | 194 | { |
195 | char *cp, *commap, *otheropts, *dp; | 195 | char *cp, *commap, *otheropts, *dp; |
196 | 196 | ||
197 | /* Binary mount data: just copy */ | 197 | /* Binary mount data: just copy */ |
198 | if (type->fs_flags & FS_BINARY_MOUNTDATA) { | 198 | if (type->fs_flags & FS_BINARY_MOUNTDATA) { |
199 | copy_page(smackopts, orig); | 199 | copy_page(smackopts, orig); |
200 | return 0; | 200 | return 0; |
201 | } | 201 | } |
202 | 202 | ||
203 | otheropts = (char *)get_zeroed_page(GFP_KERNEL); | 203 | otheropts = (char *)get_zeroed_page(GFP_KERNEL); |
204 | if (otheropts == NULL) | 204 | if (otheropts == NULL) |
205 | return -ENOMEM; | 205 | return -ENOMEM; |
206 | 206 | ||
207 | for (cp = orig, commap = orig; commap != NULL; cp = commap + 1) { | 207 | for (cp = orig, commap = orig; commap != NULL; cp = commap + 1) { |
208 | if (strstr(cp, SMK_FSDEFAULT) == cp) | 208 | if (strstr(cp, SMK_FSDEFAULT) == cp) |
209 | dp = smackopts; | 209 | dp = smackopts; |
210 | else if (strstr(cp, SMK_FSFLOOR) == cp) | 210 | else if (strstr(cp, SMK_FSFLOOR) == cp) |
211 | dp = smackopts; | 211 | dp = smackopts; |
212 | else if (strstr(cp, SMK_FSHAT) == cp) | 212 | else if (strstr(cp, SMK_FSHAT) == cp) |
213 | dp = smackopts; | 213 | dp = smackopts; |
214 | else if (strstr(cp, SMK_FSROOT) == cp) | 214 | else if (strstr(cp, SMK_FSROOT) == cp) |
215 | dp = smackopts; | 215 | dp = smackopts; |
216 | else | 216 | else |
217 | dp = otheropts; | 217 | dp = otheropts; |
218 | 218 | ||
219 | commap = strchr(cp, ','); | 219 | commap = strchr(cp, ','); |
220 | if (commap != NULL) | 220 | if (commap != NULL) |
221 | *commap = '\0'; | 221 | *commap = '\0'; |
222 | 222 | ||
223 | if (*dp != '\0') | 223 | if (*dp != '\0') |
224 | strcat(dp, ","); | 224 | strcat(dp, ","); |
225 | strcat(dp, cp); | 225 | strcat(dp, cp); |
226 | } | 226 | } |
227 | 227 | ||
228 | strcpy(orig, otheropts); | 228 | strcpy(orig, otheropts); |
229 | free_page((unsigned long)otheropts); | 229 | free_page((unsigned long)otheropts); |
230 | 230 | ||
231 | return 0; | 231 | return 0; |
232 | } | 232 | } |
233 | 233 | ||
234 | /** | 234 | /** |
235 | * smack_sb_kern_mount - Smack specific mount processing | 235 | * smack_sb_kern_mount - Smack specific mount processing |
236 | * @sb: the file system superblock | 236 | * @sb: the file system superblock |
237 | * @data: the smack mount options | 237 | * @data: the smack mount options |
238 | * | 238 | * |
239 | * Returns 0 on success, an error code on failure | 239 | * Returns 0 on success, an error code on failure |
240 | */ | 240 | */ |
241 | static int smack_sb_kern_mount(struct super_block *sb, void *data) | 241 | static int smack_sb_kern_mount(struct super_block *sb, void *data) |
242 | { | 242 | { |
243 | struct dentry *root = sb->s_root; | 243 | struct dentry *root = sb->s_root; |
244 | struct inode *inode = root->d_inode; | 244 | struct inode *inode = root->d_inode; |
245 | struct superblock_smack *sp = sb->s_security; | 245 | struct superblock_smack *sp = sb->s_security; |
246 | struct inode_smack *isp; | 246 | struct inode_smack *isp; |
247 | char *op; | 247 | char *op; |
248 | char *commap; | 248 | char *commap; |
249 | char *nsp; | 249 | char *nsp; |
250 | 250 | ||
251 | spin_lock(&sp->smk_sblock); | 251 | spin_lock(&sp->smk_sblock); |
252 | if (sp->smk_initialized != 0) { | 252 | if (sp->smk_initialized != 0) { |
253 | spin_unlock(&sp->smk_sblock); | 253 | spin_unlock(&sp->smk_sblock); |
254 | return 0; | 254 | return 0; |
255 | } | 255 | } |
256 | sp->smk_initialized = 1; | 256 | sp->smk_initialized = 1; |
257 | spin_unlock(&sp->smk_sblock); | 257 | spin_unlock(&sp->smk_sblock); |
258 | 258 | ||
259 | for (op = data; op != NULL; op = commap) { | 259 | for (op = data; op != NULL; op = commap) { |
260 | commap = strchr(op, ','); | 260 | commap = strchr(op, ','); |
261 | if (commap != NULL) | 261 | if (commap != NULL) |
262 | *commap++ = '\0'; | 262 | *commap++ = '\0'; |
263 | 263 | ||
264 | if (strncmp(op, SMK_FSHAT, strlen(SMK_FSHAT)) == 0) { | 264 | if (strncmp(op, SMK_FSHAT, strlen(SMK_FSHAT)) == 0) { |
265 | op += strlen(SMK_FSHAT); | 265 | op += strlen(SMK_FSHAT); |
266 | nsp = smk_import(op, 0); | 266 | nsp = smk_import(op, 0); |
267 | if (nsp != NULL) | 267 | if (nsp != NULL) |
268 | sp->smk_hat = nsp; | 268 | sp->smk_hat = nsp; |
269 | } else if (strncmp(op, SMK_FSFLOOR, strlen(SMK_FSFLOOR)) == 0) { | 269 | } else if (strncmp(op, SMK_FSFLOOR, strlen(SMK_FSFLOOR)) == 0) { |
270 | op += strlen(SMK_FSFLOOR); | 270 | op += strlen(SMK_FSFLOOR); |
271 | nsp = smk_import(op, 0); | 271 | nsp = smk_import(op, 0); |
272 | if (nsp != NULL) | 272 | if (nsp != NULL) |
273 | sp->smk_floor = nsp; | 273 | sp->smk_floor = nsp; |
274 | } else if (strncmp(op, SMK_FSDEFAULT, | 274 | } else if (strncmp(op, SMK_FSDEFAULT, |
275 | strlen(SMK_FSDEFAULT)) == 0) { | 275 | strlen(SMK_FSDEFAULT)) == 0) { |
276 | op += strlen(SMK_FSDEFAULT); | 276 | op += strlen(SMK_FSDEFAULT); |
277 | nsp = smk_import(op, 0); | 277 | nsp = smk_import(op, 0); |
278 | if (nsp != NULL) | 278 | if (nsp != NULL) |
279 | sp->smk_default = nsp; | 279 | sp->smk_default = nsp; |
280 | } else if (strncmp(op, SMK_FSROOT, strlen(SMK_FSROOT)) == 0) { | 280 | } else if (strncmp(op, SMK_FSROOT, strlen(SMK_FSROOT)) == 0) { |
281 | op += strlen(SMK_FSROOT); | 281 | op += strlen(SMK_FSROOT); |
282 | nsp = smk_import(op, 0); | 282 | nsp = smk_import(op, 0); |
283 | if (nsp != NULL) | 283 | if (nsp != NULL) |
284 | sp->smk_root = nsp; | 284 | sp->smk_root = nsp; |
285 | } | 285 | } |
286 | } | 286 | } |
287 | 287 | ||
288 | /* | 288 | /* |
289 | * Initialize the root inode. | 289 | * Initialize the root inode. |
290 | */ | 290 | */ |
291 | isp = inode->i_security; | 291 | isp = inode->i_security; |
292 | if (isp == NULL) | 292 | if (isp == NULL) |
293 | inode->i_security = new_inode_smack(sp->smk_root); | 293 | inode->i_security = new_inode_smack(sp->smk_root); |
294 | else | 294 | else |
295 | isp->smk_inode = sp->smk_root; | 295 | isp->smk_inode = sp->smk_root; |
296 | 296 | ||
297 | return 0; | 297 | return 0; |
298 | } | 298 | } |
299 | 299 | ||
300 | /** | 300 | /** |
301 | * smack_sb_statfs - Smack check on statfs | 301 | * smack_sb_statfs - Smack check on statfs |
302 | * @dentry: identifies the file system in question | 302 | * @dentry: identifies the file system in question |
303 | * | 303 | * |
304 | * Returns 0 if current can read the floor of the filesystem, | 304 | * Returns 0 if current can read the floor of the filesystem, |
305 | * and error code otherwise | 305 | * and error code otherwise |
306 | */ | 306 | */ |
307 | static int smack_sb_statfs(struct dentry *dentry) | 307 | static int smack_sb_statfs(struct dentry *dentry) |
308 | { | 308 | { |
309 | struct superblock_smack *sbp = dentry->d_sb->s_security; | 309 | struct superblock_smack *sbp = dentry->d_sb->s_security; |
310 | 310 | ||
311 | return smk_curacc(sbp->smk_floor, MAY_READ); | 311 | return smk_curacc(sbp->smk_floor, MAY_READ); |
312 | } | 312 | } |
313 | 313 | ||
314 | /** | 314 | /** |
315 | * smack_sb_mount - Smack check for mounting | 315 | * smack_sb_mount - Smack check for mounting |
316 | * @dev_name: unused | 316 | * @dev_name: unused |
317 | * @nd: mount point | 317 | * @nd: mount point |
318 | * @type: unused | 318 | * @type: unused |
319 | * @flags: unused | 319 | * @flags: unused |
320 | * @data: unused | 320 | * @data: unused |
321 | * | 321 | * |
322 | * Returns 0 if current can write the floor of the filesystem | 322 | * Returns 0 if current can write the floor of the filesystem |
323 | * being mounted on, an error code otherwise. | 323 | * being mounted on, an error code otherwise. |
324 | */ | 324 | */ |
325 | static int smack_sb_mount(char *dev_name, struct nameidata *nd, | 325 | static int smack_sb_mount(char *dev_name, struct nameidata *nd, |
326 | char *type, unsigned long flags, void *data) | 326 | char *type, unsigned long flags, void *data) |
327 | { | 327 | { |
328 | struct superblock_smack *sbp = nd->path.mnt->mnt_sb->s_security; | 328 | struct superblock_smack *sbp = nd->path.mnt->mnt_sb->s_security; |
329 | 329 | ||
330 | return smk_curacc(sbp->smk_floor, MAY_WRITE); | 330 | return smk_curacc(sbp->smk_floor, MAY_WRITE); |
331 | } | 331 | } |
332 | 332 | ||
333 | /** | 333 | /** |
334 | * smack_sb_umount - Smack check for unmounting | 334 | * smack_sb_umount - Smack check for unmounting |
335 | * @mnt: file system to unmount | 335 | * @mnt: file system to unmount |
336 | * @flags: unused | 336 | * @flags: unused |
337 | * | 337 | * |
338 | * Returns 0 if current can write the floor of the filesystem | 338 | * Returns 0 if current can write the floor of the filesystem |
339 | * being unmounted, an error code otherwise. | 339 | * being unmounted, an error code otherwise. |
340 | */ | 340 | */ |
341 | static int smack_sb_umount(struct vfsmount *mnt, int flags) | 341 | static int smack_sb_umount(struct vfsmount *mnt, int flags) |
342 | { | 342 | { |
343 | struct superblock_smack *sbp; | 343 | struct superblock_smack *sbp; |
344 | 344 | ||
345 | sbp = mnt->mnt_sb->s_security; | 345 | sbp = mnt->mnt_sb->s_security; |
346 | 346 | ||
347 | return smk_curacc(sbp->smk_floor, MAY_WRITE); | 347 | return smk_curacc(sbp->smk_floor, MAY_WRITE); |
348 | } | 348 | } |
349 | 349 | ||
350 | /* | 350 | /* |
351 | * Inode hooks | 351 | * Inode hooks |
352 | */ | 352 | */ |
353 | 353 | ||
354 | /** | 354 | /** |
355 | * smack_inode_alloc_security - allocate an inode blob | 355 | * smack_inode_alloc_security - allocate an inode blob |
356 | * @inode - the inode in need of a blob | 356 | * @inode - the inode in need of a blob |
357 | * | 357 | * |
358 | * Returns 0 if it gets a blob, -ENOMEM otherwise | 358 | * Returns 0 if it gets a blob, -ENOMEM otherwise |
359 | */ | 359 | */ |
360 | static int smack_inode_alloc_security(struct inode *inode) | 360 | static int smack_inode_alloc_security(struct inode *inode) |
361 | { | 361 | { |
362 | inode->i_security = new_inode_smack(current->security); | 362 | inode->i_security = new_inode_smack(current->security); |
363 | if (inode->i_security == NULL) | 363 | if (inode->i_security == NULL) |
364 | return -ENOMEM; | 364 | return -ENOMEM; |
365 | return 0; | 365 | return 0; |
366 | } | 366 | } |
367 | 367 | ||
368 | /** | 368 | /** |
369 | * smack_inode_free_security - free an inode blob | 369 | * smack_inode_free_security - free an inode blob |
370 | * @inode - the inode with a blob | 370 | * @inode - the inode with a blob |
371 | * | 371 | * |
372 | * Clears the blob pointer in inode | 372 | * Clears the blob pointer in inode |
373 | */ | 373 | */ |
374 | static void smack_inode_free_security(struct inode *inode) | 374 | static void smack_inode_free_security(struct inode *inode) |
375 | { | 375 | { |
376 | kfree(inode->i_security); | 376 | kfree(inode->i_security); |
377 | inode->i_security = NULL; | 377 | inode->i_security = NULL; |
378 | } | 378 | } |
379 | 379 | ||
380 | /** | 380 | /** |
381 | * smack_inode_init_security - copy out the smack from an inode | 381 | * smack_inode_init_security - copy out the smack from an inode |
382 | * @inode: the inode | 382 | * @inode: the inode |
383 | * @dir: unused | 383 | * @dir: unused |
384 | * @name: where to put the attribute name | 384 | * @name: where to put the attribute name |
385 | * @value: where to put the attribute value | 385 | * @value: where to put the attribute value |
386 | * @len: where to put the length of the attribute | 386 | * @len: where to put the length of the attribute |
387 | * | 387 | * |
388 | * Returns 0 if it all works out, -ENOMEM if there's no memory | 388 | * Returns 0 if it all works out, -ENOMEM if there's no memory |
389 | */ | 389 | */ |
390 | static int smack_inode_init_security(struct inode *inode, struct inode *dir, | 390 | static int smack_inode_init_security(struct inode *inode, struct inode *dir, |
391 | char **name, void **value, size_t *len) | 391 | char **name, void **value, size_t *len) |
392 | { | 392 | { |
393 | char *isp = smk_of_inode(inode); | 393 | char *isp = smk_of_inode(inode); |
394 | 394 | ||
395 | if (name) { | 395 | if (name) { |
396 | *name = kstrdup(XATTR_SMACK_SUFFIX, GFP_KERNEL); | 396 | *name = kstrdup(XATTR_SMACK_SUFFIX, GFP_KERNEL); |
397 | if (*name == NULL) | 397 | if (*name == NULL) |
398 | return -ENOMEM; | 398 | return -ENOMEM; |
399 | } | 399 | } |
400 | 400 | ||
401 | if (value) { | 401 | if (value) { |
402 | *value = kstrdup(isp, GFP_KERNEL); | 402 | *value = kstrdup(isp, GFP_KERNEL); |
403 | if (*value == NULL) | 403 | if (*value == NULL) |
404 | return -ENOMEM; | 404 | return -ENOMEM; |
405 | } | 405 | } |
406 | 406 | ||
407 | if (len) | 407 | if (len) |
408 | *len = strlen(isp) + 1; | 408 | *len = strlen(isp) + 1; |
409 | 409 | ||
410 | return 0; | 410 | return 0; |
411 | } | 411 | } |
412 | 412 | ||
413 | /** | 413 | /** |
414 | * smack_inode_link - Smack check on link | 414 | * smack_inode_link - Smack check on link |
415 | * @old_dentry: the existing object | 415 | * @old_dentry: the existing object |
416 | * @dir: unused | 416 | * @dir: unused |
417 | * @new_dentry: the new object | 417 | * @new_dentry: the new object |
418 | * | 418 | * |
419 | * Returns 0 if access is permitted, an error code otherwise | 419 | * Returns 0 if access is permitted, an error code otherwise |
420 | */ | 420 | */ |
421 | static int smack_inode_link(struct dentry *old_dentry, struct inode *dir, | 421 | static int smack_inode_link(struct dentry *old_dentry, struct inode *dir, |
422 | struct dentry *new_dentry) | 422 | struct dentry *new_dentry) |
423 | { | 423 | { |
424 | int rc; | 424 | int rc; |
425 | char *isp; | 425 | char *isp; |
426 | 426 | ||
427 | isp = smk_of_inode(old_dentry->d_inode); | 427 | isp = smk_of_inode(old_dentry->d_inode); |
428 | rc = smk_curacc(isp, MAY_WRITE); | 428 | rc = smk_curacc(isp, MAY_WRITE); |
429 | 429 | ||
430 | if (rc == 0 && new_dentry->d_inode != NULL) { | 430 | if (rc == 0 && new_dentry->d_inode != NULL) { |
431 | isp = smk_of_inode(new_dentry->d_inode); | 431 | isp = smk_of_inode(new_dentry->d_inode); |
432 | rc = smk_curacc(isp, MAY_WRITE); | 432 | rc = smk_curacc(isp, MAY_WRITE); |
433 | } | 433 | } |
434 | 434 | ||
435 | return rc; | 435 | return rc; |
436 | } | 436 | } |
437 | 437 | ||
438 | /** | 438 | /** |
439 | * smack_inode_unlink - Smack check on inode deletion | 439 | * smack_inode_unlink - Smack check on inode deletion |
440 | * @dir: containing directory object | 440 | * @dir: containing directory object |
441 | * @dentry: file to unlink | 441 | * @dentry: file to unlink |
442 | * | 442 | * |
443 | * Returns 0 if current can write the containing directory | 443 | * Returns 0 if current can write the containing directory |
444 | * and the object, error code otherwise | 444 | * and the object, error code otherwise |
445 | */ | 445 | */ |
446 | static int smack_inode_unlink(struct inode *dir, struct dentry *dentry) | 446 | static int smack_inode_unlink(struct inode *dir, struct dentry *dentry) |
447 | { | 447 | { |
448 | struct inode *ip = dentry->d_inode; | 448 | struct inode *ip = dentry->d_inode; |
449 | int rc; | 449 | int rc; |
450 | 450 | ||
451 | /* | 451 | /* |
452 | * You need write access to the thing you're unlinking | 452 | * You need write access to the thing you're unlinking |
453 | */ | 453 | */ |
454 | rc = smk_curacc(smk_of_inode(ip), MAY_WRITE); | 454 | rc = smk_curacc(smk_of_inode(ip), MAY_WRITE); |
455 | if (rc == 0) | 455 | if (rc == 0) |
456 | /* | 456 | /* |
457 | * You also need write access to the containing directory | 457 | * You also need write access to the containing directory |
458 | */ | 458 | */ |
459 | rc = smk_curacc(smk_of_inode(dir), MAY_WRITE); | 459 | rc = smk_curacc(smk_of_inode(dir), MAY_WRITE); |
460 | 460 | ||
461 | return rc; | 461 | return rc; |
462 | } | 462 | } |
463 | 463 | ||
464 | /** | 464 | /** |
465 | * smack_inode_rmdir - Smack check on directory deletion | 465 | * smack_inode_rmdir - Smack check on directory deletion |
466 | * @dir: containing directory object | 466 | * @dir: containing directory object |
467 | * @dentry: directory to unlink | 467 | * @dentry: directory to unlink |
468 | * | 468 | * |
469 | * Returns 0 if current can write the containing directory | 469 | * Returns 0 if current can write the containing directory |
470 | * and the directory, error code otherwise | 470 | * and the directory, error code otherwise |
471 | */ | 471 | */ |
472 | static int smack_inode_rmdir(struct inode *dir, struct dentry *dentry) | 472 | static int smack_inode_rmdir(struct inode *dir, struct dentry *dentry) |
473 | { | 473 | { |
474 | int rc; | 474 | int rc; |
475 | 475 | ||
476 | /* | 476 | /* |
477 | * You need write access to the thing you're removing | 477 | * You need write access to the thing you're removing |
478 | */ | 478 | */ |
479 | rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE); | 479 | rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE); |
480 | if (rc == 0) | 480 | if (rc == 0) |
481 | /* | 481 | /* |
482 | * You also need write access to the containing directory | 482 | * You also need write access to the containing directory |
483 | */ | 483 | */ |
484 | rc = smk_curacc(smk_of_inode(dir), MAY_WRITE); | 484 | rc = smk_curacc(smk_of_inode(dir), MAY_WRITE); |
485 | 485 | ||
486 | return rc; | 486 | return rc; |
487 | } | 487 | } |
488 | 488 | ||
489 | /** | 489 | /** |
490 | * smack_inode_rename - Smack check on rename | 490 | * smack_inode_rename - Smack check on rename |
491 | * @old_inode: the old directory | 491 | * @old_inode: the old directory |
492 | * @old_dentry: unused | 492 | * @old_dentry: unused |
493 | * @new_inode: the new directory | 493 | * @new_inode: the new directory |
494 | * @new_dentry: unused | 494 | * @new_dentry: unused |
495 | * | 495 | * |
496 | * Read and write access is required on both the old and | 496 | * Read and write access is required on both the old and |
497 | * new directories. | 497 | * new directories. |
498 | * | 498 | * |
499 | * Returns 0 if access is permitted, an error code otherwise | 499 | * Returns 0 if access is permitted, an error code otherwise |
500 | */ | 500 | */ |
501 | static int smack_inode_rename(struct inode *old_inode, | 501 | static int smack_inode_rename(struct inode *old_inode, |
502 | struct dentry *old_dentry, | 502 | struct dentry *old_dentry, |
503 | struct inode *new_inode, | 503 | struct inode *new_inode, |
504 | struct dentry *new_dentry) | 504 | struct dentry *new_dentry) |
505 | { | 505 | { |
506 | int rc; | 506 | int rc; |
507 | char *isp; | 507 | char *isp; |
508 | 508 | ||
509 | isp = smk_of_inode(old_dentry->d_inode); | 509 | isp = smk_of_inode(old_dentry->d_inode); |
510 | rc = smk_curacc(isp, MAY_READWRITE); | 510 | rc = smk_curacc(isp, MAY_READWRITE); |
511 | 511 | ||
512 | if (rc == 0 && new_dentry->d_inode != NULL) { | 512 | if (rc == 0 && new_dentry->d_inode != NULL) { |
513 | isp = smk_of_inode(new_dentry->d_inode); | 513 | isp = smk_of_inode(new_dentry->d_inode); |
514 | rc = smk_curacc(isp, MAY_READWRITE); | 514 | rc = smk_curacc(isp, MAY_READWRITE); |
515 | } | 515 | } |
516 | 516 | ||
517 | return rc; | 517 | return rc; |
518 | } | 518 | } |
519 | 519 | ||
520 | /** | 520 | /** |
521 | * smack_inode_permission - Smack version of permission() | 521 | * smack_inode_permission - Smack version of permission() |
522 | * @inode: the inode in question | 522 | * @inode: the inode in question |
523 | * @mask: the access requested | 523 | * @mask: the access requested |
524 | * @nd: unused | 524 | * @nd: unused |
525 | * | 525 | * |
526 | * This is the important Smack hook. | 526 | * This is the important Smack hook. |
527 | * | 527 | * |
528 | * Returns 0 if access is permitted, -EACCES otherwise | 528 | * Returns 0 if access is permitted, -EACCES otherwise |
529 | */ | 529 | */ |
530 | static int smack_inode_permission(struct inode *inode, int mask, | 530 | static int smack_inode_permission(struct inode *inode, int mask, |
531 | struct nameidata *nd) | 531 | struct nameidata *nd) |
532 | { | 532 | { |
533 | /* | 533 | /* |
534 | * No permission to check. Existence test. Yup, it's there. | 534 | * No permission to check. Existence test. Yup, it's there. |
535 | */ | 535 | */ |
536 | if (mask == 0) | 536 | if (mask == 0) |
537 | return 0; | 537 | return 0; |
538 | 538 | ||
539 | return smk_curacc(smk_of_inode(inode), mask); | 539 | return smk_curacc(smk_of_inode(inode), mask); |
540 | } | 540 | } |
541 | 541 | ||
542 | /** | 542 | /** |
543 | * smack_inode_setattr - Smack check for setting attributes | 543 | * smack_inode_setattr - Smack check for setting attributes |
544 | * @dentry: the object | 544 | * @dentry: the object |
545 | * @iattr: for the force flag | 545 | * @iattr: for the force flag |
546 | * | 546 | * |
547 | * Returns 0 if access is permitted, an error code otherwise | 547 | * Returns 0 if access is permitted, an error code otherwise |
548 | */ | 548 | */ |
549 | static int smack_inode_setattr(struct dentry *dentry, struct iattr *iattr) | 549 | static int smack_inode_setattr(struct dentry *dentry, struct iattr *iattr) |
550 | { | 550 | { |
551 | /* | 551 | /* |
552 | * Need to allow for clearing the setuid bit. | 552 | * Need to allow for clearing the setuid bit. |
553 | */ | 553 | */ |
554 | if (iattr->ia_valid & ATTR_FORCE) | 554 | if (iattr->ia_valid & ATTR_FORCE) |
555 | return 0; | 555 | return 0; |
556 | 556 | ||
557 | return smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE); | 557 | return smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE); |
558 | } | 558 | } |
559 | 559 | ||
560 | /** | 560 | /** |
561 | * smack_inode_getattr - Smack check for getting attributes | 561 | * smack_inode_getattr - Smack check for getting attributes |
562 | * @mnt: unused | 562 | * @mnt: unused |
563 | * @dentry: the object | 563 | * @dentry: the object |
564 | * | 564 | * |
565 | * Returns 0 if access is permitted, an error code otherwise | 565 | * Returns 0 if access is permitted, an error code otherwise |
566 | */ | 566 | */ |
567 | static int smack_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) | 567 | static int smack_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) |
568 | { | 568 | { |
569 | return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ); | 569 | return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ); |
570 | } | 570 | } |
571 | 571 | ||
572 | /** | 572 | /** |
573 | * smack_inode_setxattr - Smack check for setting xattrs | 573 | * smack_inode_setxattr - Smack check for setting xattrs |
574 | * @dentry: the object | 574 | * @dentry: the object |
575 | * @name: name of the attribute | 575 | * @name: name of the attribute |
576 | * @value: unused | 576 | * @value: unused |
577 | * @size: unused | 577 | * @size: unused |
578 | * @flags: unused | 578 | * @flags: unused |
579 | * | 579 | * |
580 | * This protects the Smack attribute explicitly. | 580 | * This protects the Smack attribute explicitly. |
581 | * | 581 | * |
582 | * Returns 0 if access is permitted, an error code otherwise | 582 | * Returns 0 if access is permitted, an error code otherwise |
583 | */ | 583 | */ |
584 | static int smack_inode_setxattr(struct dentry *dentry, char *name, | 584 | static int smack_inode_setxattr(struct dentry *dentry, char *name, |
585 | void *value, size_t size, int flags) | 585 | void *value, size_t size, int flags) |
586 | { | 586 | { |
587 | if (!capable(CAP_MAC_ADMIN)) { | 587 | if (!capable(CAP_MAC_ADMIN)) { |
588 | if (strcmp(name, XATTR_NAME_SMACK) == 0 || | 588 | if (strcmp(name, XATTR_NAME_SMACK) == 0 || |
589 | strcmp(name, XATTR_NAME_SMACKIPIN) == 0 || | 589 | strcmp(name, XATTR_NAME_SMACKIPIN) == 0 || |
590 | strcmp(name, XATTR_NAME_SMACKIPOUT) == 0) | 590 | strcmp(name, XATTR_NAME_SMACKIPOUT) == 0) |
591 | return -EPERM; | 591 | return -EPERM; |
592 | } | 592 | } |
593 | 593 | ||
594 | return smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE); | 594 | return smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE); |
595 | } | 595 | } |
596 | 596 | ||
597 | /** | 597 | /** |
598 | * smack_inode_post_setxattr - Apply the Smack update approved above | 598 | * smack_inode_post_setxattr - Apply the Smack update approved above |
599 | * @dentry: object | 599 | * @dentry: object |
600 | * @name: attribute name | 600 | * @name: attribute name |
601 | * @value: attribute value | 601 | * @value: attribute value |
602 | * @size: attribute size | 602 | * @size: attribute size |
603 | * @flags: unused | 603 | * @flags: unused |
604 | * | 604 | * |
605 | * Set the pointer in the inode blob to the entry found | 605 | * Set the pointer in the inode blob to the entry found |
606 | * in the master label list. | 606 | * in the master label list. |
607 | */ | 607 | */ |
608 | static void smack_inode_post_setxattr(struct dentry *dentry, char *name, | 608 | static void smack_inode_post_setxattr(struct dentry *dentry, char *name, |
609 | void *value, size_t size, int flags) | 609 | void *value, size_t size, int flags) |
610 | { | 610 | { |
611 | struct inode_smack *isp; | 611 | struct inode_smack *isp; |
612 | char *nsp; | 612 | char *nsp; |
613 | 613 | ||
614 | /* | 614 | /* |
615 | * Not SMACK | 615 | * Not SMACK |
616 | */ | 616 | */ |
617 | if (strcmp(name, XATTR_NAME_SMACK)) | 617 | if (strcmp(name, XATTR_NAME_SMACK)) |
618 | return; | 618 | return; |
619 | 619 | ||
620 | if (size >= SMK_LABELLEN) | 620 | if (size >= SMK_LABELLEN) |
621 | return; | 621 | return; |
622 | 622 | ||
623 | isp = dentry->d_inode->i_security; | 623 | isp = dentry->d_inode->i_security; |
624 | 624 | ||
625 | /* | 625 | /* |
626 | * No locking is done here. This is a pointer | 626 | * No locking is done here. This is a pointer |
627 | * assignment. | 627 | * assignment. |
628 | */ | 628 | */ |
629 | nsp = smk_import(value, size); | 629 | nsp = smk_import(value, size); |
630 | if (nsp != NULL) | 630 | if (nsp != NULL) |
631 | isp->smk_inode = nsp; | 631 | isp->smk_inode = nsp; |
632 | else | 632 | else |
633 | isp->smk_inode = smack_known_invalid.smk_known; | 633 | isp->smk_inode = smack_known_invalid.smk_known; |
634 | 634 | ||
635 | return; | 635 | return; |
636 | } | 636 | } |
637 | 637 | ||
638 | /* | 638 | /* |
639 | * smack_inode_getxattr - Smack check on getxattr | 639 | * smack_inode_getxattr - Smack check on getxattr |
640 | * @dentry: the object | 640 | * @dentry: the object |
641 | * @name: unused | 641 | * @name: unused |
642 | * | 642 | * |
643 | * Returns 0 if access is permitted, an error code otherwise | 643 | * Returns 0 if access is permitted, an error code otherwise |
644 | */ | 644 | */ |
645 | static int smack_inode_getxattr(struct dentry *dentry, char *name) | 645 | static int smack_inode_getxattr(struct dentry *dentry, char *name) |
646 | { | 646 | { |
647 | return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ); | 647 | return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ); |
648 | } | 648 | } |
649 | 649 | ||
650 | /* | 650 | /* |
651 | * smack_inode_removexattr - Smack check on removexattr | 651 | * smack_inode_removexattr - Smack check on removexattr |
652 | * @dentry: the object | 652 | * @dentry: the object |
653 | * @name: name of the attribute | 653 | * @name: name of the attribute |
654 | * | 654 | * |
655 | * Removing the Smack attribute requires CAP_MAC_ADMIN | 655 | * Removing the Smack attribute requires CAP_MAC_ADMIN |
656 | * | 656 | * |
657 | * Returns 0 if access is permitted, an error code otherwise | 657 | * Returns 0 if access is permitted, an error code otherwise |
658 | */ | 658 | */ |
659 | static int smack_inode_removexattr(struct dentry *dentry, char *name) | 659 | static int smack_inode_removexattr(struct dentry *dentry, char *name) |
660 | { | 660 | { |
661 | if (strcmp(name, XATTR_NAME_SMACK) == 0 && !capable(CAP_MAC_ADMIN)) | 661 | if (strcmp(name, XATTR_NAME_SMACK) == 0 && !capable(CAP_MAC_ADMIN)) |
662 | return -EPERM; | 662 | return -EPERM; |
663 | 663 | ||
664 | return smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE); | 664 | return smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE); |
665 | } | 665 | } |
666 | 666 | ||
667 | /** | 667 | /** |
668 | * smack_inode_getsecurity - get smack xattrs | 668 | * smack_inode_getsecurity - get smack xattrs |
669 | * @inode: the object | 669 | * @inode: the object |
670 | * @name: attribute name | 670 | * @name: attribute name |
671 | * @buffer: where to put the result | 671 | * @buffer: where to put the result |
672 | * @size: size of the buffer | 672 | * @size: size of the buffer |
673 | * @err: unused | 673 | * @err: unused |
674 | * | 674 | * |
675 | * Returns the size of the attribute or an error code | 675 | * Returns the size of the attribute or an error code |
676 | */ | 676 | */ |
677 | static int smack_inode_getsecurity(const struct inode *inode, | 677 | static int smack_inode_getsecurity(const struct inode *inode, |
678 | const char *name, void **buffer, | 678 | const char *name, void **buffer, |
679 | bool alloc) | 679 | bool alloc) |
680 | { | 680 | { |
681 | struct socket_smack *ssp; | 681 | struct socket_smack *ssp; |
682 | struct socket *sock; | 682 | struct socket *sock; |
683 | struct super_block *sbp; | 683 | struct super_block *sbp; |
684 | struct inode *ip = (struct inode *)inode; | 684 | struct inode *ip = (struct inode *)inode; |
685 | char *isp; | 685 | char *isp; |
686 | int ilen; | 686 | int ilen; |
687 | int rc = 0; | 687 | int rc = 0; |
688 | 688 | ||
689 | if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) { | 689 | if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) { |
690 | isp = smk_of_inode(inode); | 690 | isp = smk_of_inode(inode); |
691 | ilen = strlen(isp) + 1; | 691 | ilen = strlen(isp) + 1; |
692 | *buffer = isp; | 692 | *buffer = isp; |
693 | return ilen; | 693 | return ilen; |
694 | } | 694 | } |
695 | 695 | ||
696 | /* | 696 | /* |
697 | * The rest of the Smack xattrs are only on sockets. | 697 | * The rest of the Smack xattrs are only on sockets. |
698 | */ | 698 | */ |
699 | sbp = ip->i_sb; | 699 | sbp = ip->i_sb; |
700 | if (sbp->s_magic != SOCKFS_MAGIC) | 700 | if (sbp->s_magic != SOCKFS_MAGIC) |
701 | return -EOPNOTSUPP; | 701 | return -EOPNOTSUPP; |
702 | 702 | ||
703 | sock = SOCKET_I(ip); | 703 | sock = SOCKET_I(ip); |
704 | if (sock == NULL || sock->sk == NULL) | 704 | if (sock == NULL || sock->sk == NULL) |
705 | return -EOPNOTSUPP; | 705 | return -EOPNOTSUPP; |
706 | 706 | ||
707 | ssp = sock->sk->sk_security; | 707 | ssp = sock->sk->sk_security; |
708 | 708 | ||
709 | if (strcmp(name, XATTR_SMACK_IPIN) == 0) | 709 | if (strcmp(name, XATTR_SMACK_IPIN) == 0) |
710 | isp = ssp->smk_in; | 710 | isp = ssp->smk_in; |
711 | else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) | 711 | else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) |
712 | isp = ssp->smk_out; | 712 | isp = ssp->smk_out; |
713 | else | 713 | else |
714 | return -EOPNOTSUPP; | 714 | return -EOPNOTSUPP; |
715 | 715 | ||
716 | ilen = strlen(isp) + 1; | 716 | ilen = strlen(isp) + 1; |
717 | if (rc == 0) { | 717 | if (rc == 0) { |
718 | *buffer = isp; | 718 | *buffer = isp; |
719 | rc = ilen; | 719 | rc = ilen; |
720 | } | 720 | } |
721 | 721 | ||
722 | return rc; | 722 | return rc; |
723 | } | 723 | } |
724 | 724 | ||
725 | 725 | ||
726 | /** | 726 | /** |
727 | * smack_inode_listsecurity - list the Smack attributes | 727 | * smack_inode_listsecurity - list the Smack attributes |
728 | * @inode: the object | 728 | * @inode: the object |
729 | * @buffer: where they go | 729 | * @buffer: where they go |
730 | * @buffer_size: size of buffer | 730 | * @buffer_size: size of buffer |
731 | * | 731 | * |
732 | * Returns 0 on success, -EINVAL otherwise | 732 | * Returns 0 on success, -EINVAL otherwise |
733 | */ | 733 | */ |
734 | static int smack_inode_listsecurity(struct inode *inode, char *buffer, | 734 | static int smack_inode_listsecurity(struct inode *inode, char *buffer, |
735 | size_t buffer_size) | 735 | size_t buffer_size) |
736 | { | 736 | { |
737 | int len = strlen(XATTR_NAME_SMACK); | 737 | int len = strlen(XATTR_NAME_SMACK); |
738 | 738 | ||
739 | if (buffer != NULL && len <= buffer_size) { | 739 | if (buffer != NULL && len <= buffer_size) { |
740 | memcpy(buffer, XATTR_NAME_SMACK, len); | 740 | memcpy(buffer, XATTR_NAME_SMACK, len); |
741 | return len; | 741 | return len; |
742 | } | 742 | } |
743 | return -EINVAL; | 743 | return -EINVAL; |
744 | } | 744 | } |
745 | 745 | ||
746 | /* | 746 | /* |
747 | * File Hooks | 747 | * File Hooks |
748 | */ | 748 | */ |
749 | 749 | ||
750 | /** | 750 | /** |
751 | * smack_file_permission - Smack check on file operations | 751 | * smack_file_permission - Smack check on file operations |
752 | * @file: unused | 752 | * @file: unused |
753 | * @mask: unused | 753 | * @mask: unused |
754 | * | 754 | * |
755 | * Returns 0 | 755 | * Returns 0 |
756 | * | 756 | * |
757 | * Should access checks be done on each read or write? | 757 | * Should access checks be done on each read or write? |
758 | * UNICOS and SELinux say yes. | 758 | * UNICOS and SELinux say yes. |
759 | * Trusted Solaris, Trusted Irix, and just about everyone else says no. | 759 | * Trusted Solaris, Trusted Irix, and just about everyone else says no. |
760 | * | 760 | * |
761 | * I'll say no for now. Smack does not do the frequent | 761 | * I'll say no for now. Smack does not do the frequent |
762 | * label changing that SELinux does. | 762 | * label changing that SELinux does. |
763 | */ | 763 | */ |
764 | static int smack_file_permission(struct file *file, int mask) | 764 | static int smack_file_permission(struct file *file, int mask) |
765 | { | 765 | { |
766 | return 0; | 766 | return 0; |
767 | } | 767 | } |
768 | 768 | ||
769 | /** | 769 | /** |
770 | * smack_file_alloc_security - assign a file security blob | 770 | * smack_file_alloc_security - assign a file security blob |
771 | * @file: the object | 771 | * @file: the object |
772 | * | 772 | * |
773 | * The security blob for a file is a pointer to the master | 773 | * The security blob for a file is a pointer to the master |
774 | * label list, so no allocation is done. | 774 | * label list, so no allocation is done. |
775 | * | 775 | * |
776 | * Returns 0 | 776 | * Returns 0 |
777 | */ | 777 | */ |
778 | static int smack_file_alloc_security(struct file *file) | 778 | static int smack_file_alloc_security(struct file *file) |
779 | { | 779 | { |
780 | file->f_security = current->security; | 780 | file->f_security = current->security; |
781 | return 0; | 781 | return 0; |
782 | } | 782 | } |
783 | 783 | ||
784 | /** | 784 | /** |
785 | * smack_file_free_security - clear a file security blob | 785 | * smack_file_free_security - clear a file security blob |
786 | * @file: the object | 786 | * @file: the object |
787 | * | 787 | * |
788 | * The security blob for a file is a pointer to the master | 788 | * The security blob for a file is a pointer to the master |
789 | * label list, so no memory is freed. | 789 | * label list, so no memory is freed. |
790 | */ | 790 | */ |
791 | static void smack_file_free_security(struct file *file) | 791 | static void smack_file_free_security(struct file *file) |
792 | { | 792 | { |
793 | file->f_security = NULL; | 793 | file->f_security = NULL; |
794 | } | 794 | } |
795 | 795 | ||
796 | /** | 796 | /** |
797 | * smack_file_ioctl - Smack check on ioctls | 797 | * smack_file_ioctl - Smack check on ioctls |
798 | * @file: the object | 798 | * @file: the object |
799 | * @cmd: what to do | 799 | * @cmd: what to do |
800 | * @arg: unused | 800 | * @arg: unused |
801 | * | 801 | * |
802 | * Relies heavily on the correct use of the ioctl command conventions. | 802 | * Relies heavily on the correct use of the ioctl command conventions. |
803 | * | 803 | * |
804 | * Returns 0 if allowed, error code otherwise | 804 | * Returns 0 if allowed, error code otherwise |
805 | */ | 805 | */ |
806 | static int smack_file_ioctl(struct file *file, unsigned int cmd, | 806 | static int smack_file_ioctl(struct file *file, unsigned int cmd, |
807 | unsigned long arg) | 807 | unsigned long arg) |
808 | { | 808 | { |
809 | int rc = 0; | 809 | int rc = 0; |
810 | 810 | ||
811 | if (_IOC_DIR(cmd) & _IOC_WRITE) | 811 | if (_IOC_DIR(cmd) & _IOC_WRITE) |
812 | rc = smk_curacc(file->f_security, MAY_WRITE); | 812 | rc = smk_curacc(file->f_security, MAY_WRITE); |
813 | 813 | ||
814 | if (rc == 0 && (_IOC_DIR(cmd) & _IOC_READ)) | 814 | if (rc == 0 && (_IOC_DIR(cmd) & _IOC_READ)) |
815 | rc = smk_curacc(file->f_security, MAY_READ); | 815 | rc = smk_curacc(file->f_security, MAY_READ); |
816 | 816 | ||
817 | return rc; | 817 | return rc; |
818 | } | 818 | } |
819 | 819 | ||
820 | /** | 820 | /** |
821 | * smack_file_lock - Smack check on file locking | 821 | * smack_file_lock - Smack check on file locking |
822 | * @file: the object | 822 | * @file: the object |
823 | * @cmd unused | 823 | * @cmd unused |
824 | * | 824 | * |
825 | * Returns 0 if current has write access, error code otherwise | 825 | * Returns 0 if current has write access, error code otherwise |
826 | */ | 826 | */ |
827 | static int smack_file_lock(struct file *file, unsigned int cmd) | 827 | static int smack_file_lock(struct file *file, unsigned int cmd) |
828 | { | 828 | { |
829 | return smk_curacc(file->f_security, MAY_WRITE); | 829 | return smk_curacc(file->f_security, MAY_WRITE); |
830 | } | 830 | } |
831 | 831 | ||
832 | /** | 832 | /** |
833 | * smack_file_fcntl - Smack check on fcntl | 833 | * smack_file_fcntl - Smack check on fcntl |
834 | * @file: the object | 834 | * @file: the object |
835 | * @cmd: what action to check | 835 | * @cmd: what action to check |
836 | * @arg: unused | 836 | * @arg: unused |
837 | * | 837 | * |
838 | * Returns 0 if current has access, error code otherwise | 838 | * Returns 0 if current has access, error code otherwise |
839 | */ | 839 | */ |
840 | static int smack_file_fcntl(struct file *file, unsigned int cmd, | 840 | static int smack_file_fcntl(struct file *file, unsigned int cmd, |
841 | unsigned long arg) | 841 | unsigned long arg) |
842 | { | 842 | { |
843 | int rc; | 843 | int rc; |
844 | 844 | ||
845 | switch (cmd) { | 845 | switch (cmd) { |
846 | case F_DUPFD: | 846 | case F_DUPFD: |
847 | case F_GETFD: | 847 | case F_GETFD: |
848 | case F_GETFL: | 848 | case F_GETFL: |
849 | case F_GETLK: | 849 | case F_GETLK: |
850 | case F_GETOWN: | 850 | case F_GETOWN: |
851 | case F_GETSIG: | 851 | case F_GETSIG: |
852 | rc = smk_curacc(file->f_security, MAY_READ); | 852 | rc = smk_curacc(file->f_security, MAY_READ); |
853 | break; | 853 | break; |
854 | case F_SETFD: | 854 | case F_SETFD: |
855 | case F_SETFL: | 855 | case F_SETFL: |
856 | case F_SETLK: | 856 | case F_SETLK: |
857 | case F_SETLKW: | 857 | case F_SETLKW: |
858 | case F_SETOWN: | 858 | case F_SETOWN: |
859 | case F_SETSIG: | 859 | case F_SETSIG: |
860 | rc = smk_curacc(file->f_security, MAY_WRITE); | 860 | rc = smk_curacc(file->f_security, MAY_WRITE); |
861 | break; | 861 | break; |
862 | default: | 862 | default: |
863 | rc = smk_curacc(file->f_security, MAY_READWRITE); | 863 | rc = smk_curacc(file->f_security, MAY_READWRITE); |
864 | } | 864 | } |
865 | 865 | ||
866 | return rc; | 866 | return rc; |
867 | } | 867 | } |
868 | 868 | ||
869 | /** | 869 | /** |
870 | * smack_file_set_fowner - set the file security blob value | 870 | * smack_file_set_fowner - set the file security blob value |
871 | * @file: object in question | 871 | * @file: object in question |
872 | * | 872 | * |
873 | * Returns 0 | 873 | * Returns 0 |
874 | * Further research may be required on this one. | 874 | * Further research may be required on this one. |
875 | */ | 875 | */ |
876 | static int smack_file_set_fowner(struct file *file) | 876 | static int smack_file_set_fowner(struct file *file) |
877 | { | 877 | { |
878 | file->f_security = current->security; | 878 | file->f_security = current->security; |
879 | return 0; | 879 | return 0; |
880 | } | 880 | } |
881 | 881 | ||
882 | /** | 882 | /** |
883 | * smack_file_send_sigiotask - Smack on sigio | 883 | * smack_file_send_sigiotask - Smack on sigio |
884 | * @tsk: The target task | 884 | * @tsk: The target task |
885 | * @fown: the object the signal come from | 885 | * @fown: the object the signal come from |
886 | * @signum: unused | 886 | * @signum: unused |
887 | * | 887 | * |
888 | * Allow a privileged task to get signals even if it shouldn't | 888 | * Allow a privileged task to get signals even if it shouldn't |
889 | * | 889 | * |
890 | * Returns 0 if a subject with the object's smack could | 890 | * Returns 0 if a subject with the object's smack could |
891 | * write to the task, an error code otherwise. | 891 | * write to the task, an error code otherwise. |
892 | */ | 892 | */ |
893 | static int smack_file_send_sigiotask(struct task_struct *tsk, | 893 | static int smack_file_send_sigiotask(struct task_struct *tsk, |
894 | struct fown_struct *fown, int signum) | 894 | struct fown_struct *fown, int signum) |
895 | { | 895 | { |
896 | struct file *file; | 896 | struct file *file; |
897 | int rc; | 897 | int rc; |
898 | 898 | ||
899 | /* | 899 | /* |
900 | * struct fown_struct is never outside the context of a struct file | 900 | * struct fown_struct is never outside the context of a struct file |
901 | */ | 901 | */ |
902 | file = container_of(fown, struct file, f_owner); | 902 | file = container_of(fown, struct file, f_owner); |
903 | rc = smk_access(file->f_security, tsk->security, MAY_WRITE); | 903 | rc = smk_access(file->f_security, tsk->security, MAY_WRITE); |
904 | if (rc != 0 && __capable(tsk, CAP_MAC_OVERRIDE)) | 904 | if (rc != 0 && __capable(tsk, CAP_MAC_OVERRIDE)) |
905 | return 0; | 905 | return 0; |
906 | return rc; | 906 | return rc; |
907 | } | 907 | } |
908 | 908 | ||
909 | /** | 909 | /** |
910 | * smack_file_receive - Smack file receive check | 910 | * smack_file_receive - Smack file receive check |
911 | * @file: the object | 911 | * @file: the object |
912 | * | 912 | * |
913 | * Returns 0 if current has access, error code otherwise | 913 | * Returns 0 if current has access, error code otherwise |
914 | */ | 914 | */ |
915 | static int smack_file_receive(struct file *file) | 915 | static int smack_file_receive(struct file *file) |
916 | { | 916 | { |
917 | int may = 0; | 917 | int may = 0; |
918 | 918 | ||
919 | /* | 919 | /* |
920 | * This code relies on bitmasks. | 920 | * This code relies on bitmasks. |
921 | */ | 921 | */ |
922 | if (file->f_mode & FMODE_READ) | 922 | if (file->f_mode & FMODE_READ) |
923 | may = MAY_READ; | 923 | may = MAY_READ; |
924 | if (file->f_mode & FMODE_WRITE) | 924 | if (file->f_mode & FMODE_WRITE) |
925 | may |= MAY_WRITE; | 925 | may |= MAY_WRITE; |
926 | 926 | ||
927 | return smk_curacc(file->f_security, may); | 927 | return smk_curacc(file->f_security, may); |
928 | } | 928 | } |
929 | 929 | ||
930 | /* | 930 | /* |
931 | * Task hooks | 931 | * Task hooks |
932 | */ | 932 | */ |
933 | 933 | ||
934 | /** | 934 | /** |
935 | * smack_task_alloc_security - "allocate" a task blob | 935 | * smack_task_alloc_security - "allocate" a task blob |
936 | * @tsk: the task in need of a blob | 936 | * @tsk: the task in need of a blob |
937 | * | 937 | * |
938 | * Smack isn't using copies of blobs. Everyone | 938 | * Smack isn't using copies of blobs. Everyone |
939 | * points to an immutable list. No alloc required. | 939 | * points to an immutable list. No alloc required. |
940 | * No data copy required. | 940 | * No data copy required. |
941 | * | 941 | * |
942 | * Always returns 0 | 942 | * Always returns 0 |
943 | */ | 943 | */ |
944 | static int smack_task_alloc_security(struct task_struct *tsk) | 944 | static int smack_task_alloc_security(struct task_struct *tsk) |
945 | { | 945 | { |
946 | tsk->security = current->security; | 946 | tsk->security = current->security; |
947 | 947 | ||
948 | return 0; | 948 | return 0; |
949 | } | 949 | } |
950 | 950 | ||
951 | /** | 951 | /** |
952 | * smack_task_free_security - "free" a task blob | 952 | * smack_task_free_security - "free" a task blob |
953 | * @task: the task with the blob | 953 | * @task: the task with the blob |
954 | * | 954 | * |
955 | * Smack isn't using copies of blobs. Everyone | 955 | * Smack isn't using copies of blobs. Everyone |
956 | * points to an immutable list. The blobs never go away. | 956 | * points to an immutable list. The blobs never go away. |
957 | * There is no leak here. | 957 | * There is no leak here. |
958 | */ | 958 | */ |
959 | static void smack_task_free_security(struct task_struct *task) | 959 | static void smack_task_free_security(struct task_struct *task) |
960 | { | 960 | { |
961 | task->security = NULL; | 961 | task->security = NULL; |
962 | } | 962 | } |
963 | 963 | ||
964 | /** | 964 | /** |
965 | * smack_task_setpgid - Smack check on setting pgid | 965 | * smack_task_setpgid - Smack check on setting pgid |
966 | * @p: the task object | 966 | * @p: the task object |
967 | * @pgid: unused | 967 | * @pgid: unused |
968 | * | 968 | * |
969 | * Return 0 if write access is permitted | 969 | * Return 0 if write access is permitted |
970 | */ | 970 | */ |
971 | static int smack_task_setpgid(struct task_struct *p, pid_t pgid) | 971 | static int smack_task_setpgid(struct task_struct *p, pid_t pgid) |
972 | { | 972 | { |
973 | return smk_curacc(p->security, MAY_WRITE); | 973 | return smk_curacc(p->security, MAY_WRITE); |
974 | } | 974 | } |
975 | 975 | ||
976 | /** | 976 | /** |
977 | * smack_task_getpgid - Smack access check for getpgid | 977 | * smack_task_getpgid - Smack access check for getpgid |
978 | * @p: the object task | 978 | * @p: the object task |
979 | * | 979 | * |
980 | * Returns 0 if current can read the object task, error code otherwise | 980 | * Returns 0 if current can read the object task, error code otherwise |
981 | */ | 981 | */ |
982 | static int smack_task_getpgid(struct task_struct *p) | 982 | static int smack_task_getpgid(struct task_struct *p) |
983 | { | 983 | { |
984 | return smk_curacc(p->security, MAY_READ); | 984 | return smk_curacc(p->security, MAY_READ); |
985 | } | 985 | } |
986 | 986 | ||
987 | /** | 987 | /** |
988 | * smack_task_getsid - Smack access check for getsid | 988 | * smack_task_getsid - Smack access check for getsid |
989 | * @p: the object task | 989 | * @p: the object task |
990 | * | 990 | * |
991 | * Returns 0 if current can read the object task, error code otherwise | 991 | * Returns 0 if current can read the object task, error code otherwise |
992 | */ | 992 | */ |
993 | static int smack_task_getsid(struct task_struct *p) | 993 | static int smack_task_getsid(struct task_struct *p) |
994 | { | 994 | { |
995 | return smk_curacc(p->security, MAY_READ); | 995 | return smk_curacc(p->security, MAY_READ); |
996 | } | 996 | } |
997 | 997 | ||
998 | /** | 998 | /** |
999 | * smack_task_getsecid - get the secid of the task | 999 | * smack_task_getsecid - get the secid of the task |
1000 | * @p: the object task | 1000 | * @p: the object task |
1001 | * @secid: where to put the result | 1001 | * @secid: where to put the result |
1002 | * | 1002 | * |
1003 | * Sets the secid to contain a u32 version of the smack label. | 1003 | * Sets the secid to contain a u32 version of the smack label. |
1004 | */ | 1004 | */ |
1005 | static void smack_task_getsecid(struct task_struct *p, u32 *secid) | 1005 | static void smack_task_getsecid(struct task_struct *p, u32 *secid) |
1006 | { | 1006 | { |
1007 | *secid = smack_to_secid(p->security); | 1007 | *secid = smack_to_secid(p->security); |
1008 | } | 1008 | } |
1009 | 1009 | ||
1010 | /** | 1010 | /** |
1011 | * smack_task_setnice - Smack check on setting nice | 1011 | * smack_task_setnice - Smack check on setting nice |
1012 | * @p: the task object | 1012 | * @p: the task object |
1013 | * @nice: unused | 1013 | * @nice: unused |
1014 | * | 1014 | * |
1015 | * Return 0 if write access is permitted | 1015 | * Return 0 if write access is permitted |
1016 | */ | 1016 | */ |
1017 | static int smack_task_setnice(struct task_struct *p, int nice) | 1017 | static int smack_task_setnice(struct task_struct *p, int nice) |
1018 | { | 1018 | { |
1019 | return smk_curacc(p->security, MAY_WRITE); | 1019 | return smk_curacc(p->security, MAY_WRITE); |
1020 | } | 1020 | } |
1021 | 1021 | ||
1022 | /** | 1022 | /** |
1023 | * smack_task_setioprio - Smack check on setting ioprio | 1023 | * smack_task_setioprio - Smack check on setting ioprio |
1024 | * @p: the task object | 1024 | * @p: the task object |
1025 | * @ioprio: unused | 1025 | * @ioprio: unused |
1026 | * | 1026 | * |
1027 | * Return 0 if write access is permitted | 1027 | * Return 0 if write access is permitted |
1028 | */ | 1028 | */ |
1029 | static int smack_task_setioprio(struct task_struct *p, int ioprio) | 1029 | static int smack_task_setioprio(struct task_struct *p, int ioprio) |
1030 | { | 1030 | { |
1031 | return smk_curacc(p->security, MAY_WRITE); | 1031 | return smk_curacc(p->security, MAY_WRITE); |
1032 | } | 1032 | } |
1033 | 1033 | ||
1034 | /** | 1034 | /** |
1035 | * smack_task_getioprio - Smack check on reading ioprio | 1035 | * smack_task_getioprio - Smack check on reading ioprio |
1036 | * @p: the task object | 1036 | * @p: the task object |
1037 | * | 1037 | * |
1038 | * Return 0 if read access is permitted | 1038 | * Return 0 if read access is permitted |
1039 | */ | 1039 | */ |
1040 | static int smack_task_getioprio(struct task_struct *p) | 1040 | static int smack_task_getioprio(struct task_struct *p) |
1041 | { | 1041 | { |
1042 | return smk_curacc(p->security, MAY_READ); | 1042 | return smk_curacc(p->security, MAY_READ); |
1043 | } | 1043 | } |
1044 | 1044 | ||
1045 | /** | 1045 | /** |
1046 | * smack_task_setscheduler - Smack check on setting scheduler | 1046 | * smack_task_setscheduler - Smack check on setting scheduler |
1047 | * @p: the task object | 1047 | * @p: the task object |
1048 | * @policy: unused | 1048 | * @policy: unused |
1049 | * @lp: unused | 1049 | * @lp: unused |
1050 | * | 1050 | * |
1051 | * Return 0 if read access is permitted | 1051 | * Return 0 if read access is permitted |
1052 | */ | 1052 | */ |
1053 | static int smack_task_setscheduler(struct task_struct *p, int policy, | 1053 | static int smack_task_setscheduler(struct task_struct *p, int policy, |
1054 | struct sched_param *lp) | 1054 | struct sched_param *lp) |
1055 | { | 1055 | { |
1056 | return smk_curacc(p->security, MAY_WRITE); | 1056 | return smk_curacc(p->security, MAY_WRITE); |
1057 | } | 1057 | } |
1058 | 1058 | ||
1059 | /** | 1059 | /** |
1060 | * smack_task_getscheduler - Smack check on reading scheduler | 1060 | * smack_task_getscheduler - Smack check on reading scheduler |
1061 | * @p: the task object | 1061 | * @p: the task object |
1062 | * | 1062 | * |
1063 | * Return 0 if read access is permitted | 1063 | * Return 0 if read access is permitted |
1064 | */ | 1064 | */ |
1065 | static int smack_task_getscheduler(struct task_struct *p) | 1065 | static int smack_task_getscheduler(struct task_struct *p) |
1066 | { | 1066 | { |
1067 | return smk_curacc(p->security, MAY_READ); | 1067 | return smk_curacc(p->security, MAY_READ); |
1068 | } | 1068 | } |
1069 | 1069 | ||
1070 | /** | 1070 | /** |
1071 | * smack_task_movememory - Smack check on moving memory | 1071 | * smack_task_movememory - Smack check on moving memory |
1072 | * @p: the task object | 1072 | * @p: the task object |
1073 | * | 1073 | * |
1074 | * Return 0 if write access is permitted | 1074 | * Return 0 if write access is permitted |
1075 | */ | 1075 | */ |
1076 | static int smack_task_movememory(struct task_struct *p) | 1076 | static int smack_task_movememory(struct task_struct *p) |
1077 | { | 1077 | { |
1078 | return smk_curacc(p->security, MAY_WRITE); | 1078 | return smk_curacc(p->security, MAY_WRITE); |
1079 | } | 1079 | } |
1080 | 1080 | ||
1081 | /** | 1081 | /** |
1082 | * smack_task_kill - Smack check on signal delivery | 1082 | * smack_task_kill - Smack check on signal delivery |
1083 | * @p: the task object | 1083 | * @p: the task object |
1084 | * @info: unused | 1084 | * @info: unused |
1085 | * @sig: unused | 1085 | * @sig: unused |
1086 | * @secid: identifies the smack to use in lieu of current's | 1086 | * @secid: identifies the smack to use in lieu of current's |
1087 | * | 1087 | * |
1088 | * Return 0 if write access is permitted | 1088 | * Return 0 if write access is permitted |
1089 | * | 1089 | * |
1090 | * The secid behavior is an artifact of an SELinux hack | 1090 | * The secid behavior is an artifact of an SELinux hack |
1091 | * in the USB code. Someday it may go away. | 1091 | * in the USB code. Someday it may go away. |
1092 | */ | 1092 | */ |
1093 | static int smack_task_kill(struct task_struct *p, struct siginfo *info, | 1093 | static int smack_task_kill(struct task_struct *p, struct siginfo *info, |
1094 | int sig, u32 secid) | 1094 | int sig, u32 secid) |
1095 | { | 1095 | { |
1096 | /* | 1096 | /* |
1097 | * Special cases where signals really ought to go through | 1097 | * Special cases where signals really ought to go through |
1098 | * in spite of policy. Stephen Smalley suggests it may | 1098 | * in spite of policy. Stephen Smalley suggests it may |
1099 | * make sense to change the caller so that it doesn't | 1099 | * make sense to change the caller so that it doesn't |
1100 | * bother with the LSM hook in these cases. | 1100 | * bother with the LSM hook in these cases. |
1101 | */ | 1101 | */ |
1102 | if (info != SEND_SIG_NOINFO && | 1102 | if (info != SEND_SIG_NOINFO && |
1103 | (is_si_special(info) || SI_FROMKERNEL(info))) | 1103 | (is_si_special(info) || SI_FROMKERNEL(info))) |
1104 | return 0; | 1104 | return 0; |
1105 | /* | 1105 | /* |
1106 | * Sending a signal requires that the sender | 1106 | * Sending a signal requires that the sender |
1107 | * can write the receiver. | 1107 | * can write the receiver. |
1108 | */ | 1108 | */ |
1109 | if (secid == 0) | 1109 | if (secid == 0) |
1110 | return smk_curacc(p->security, MAY_WRITE); | 1110 | return smk_curacc(p->security, MAY_WRITE); |
1111 | /* | 1111 | /* |
1112 | * If the secid isn't 0 we're dealing with some USB IO | 1112 | * If the secid isn't 0 we're dealing with some USB IO |
1113 | * specific behavior. This is not clean. For one thing | 1113 | * specific behavior. This is not clean. For one thing |
1114 | * we can't take privilege into account. | 1114 | * we can't take privilege into account. |
1115 | */ | 1115 | */ |
1116 | return smk_access(smack_from_secid(secid), p->security, MAY_WRITE); | 1116 | return smk_access(smack_from_secid(secid), p->security, MAY_WRITE); |
1117 | } | 1117 | } |
1118 | 1118 | ||
1119 | /** | 1119 | /** |
1120 | * smack_task_wait - Smack access check for waiting | 1120 | * smack_task_wait - Smack access check for waiting |
1121 | * @p: task to wait for | 1121 | * @p: task to wait for |
1122 | * | 1122 | * |
1123 | * Returns 0 if current can wait for p, error code otherwise | 1123 | * Returns 0 if current can wait for p, error code otherwise |
1124 | */ | 1124 | */ |
1125 | static int smack_task_wait(struct task_struct *p) | 1125 | static int smack_task_wait(struct task_struct *p) |
1126 | { | 1126 | { |
1127 | int rc; | 1127 | int rc; |
1128 | 1128 | ||
1129 | rc = smk_access(current->security, p->security, MAY_WRITE); | 1129 | rc = smk_access(current->security, p->security, MAY_WRITE); |
1130 | if (rc == 0) | 1130 | if (rc == 0) |
1131 | return 0; | 1131 | return 0; |
1132 | 1132 | ||
1133 | /* | 1133 | /* |
1134 | * Allow the operation to succeed if either task | 1134 | * Allow the operation to succeed if either task |
1135 | * has privilege to perform operations that might | 1135 | * has privilege to perform operations that might |
1136 | * account for the smack labels having gotten to | 1136 | * account for the smack labels having gotten to |
1137 | * be different in the first place. | 1137 | * be different in the first place. |
1138 | * | 1138 | * |
1139 | * This breaks the strict subjet/object access | 1139 | * This breaks the strict subjet/object access |
1140 | * control ideal, taking the object's privilege | 1140 | * control ideal, taking the object's privilege |
1141 | * state into account in the decision as well as | 1141 | * state into account in the decision as well as |
1142 | * the smack value. | 1142 | * the smack value. |
1143 | */ | 1143 | */ |
1144 | if (capable(CAP_MAC_OVERRIDE) || __capable(p, CAP_MAC_OVERRIDE)) | 1144 | if (capable(CAP_MAC_OVERRIDE) || __capable(p, CAP_MAC_OVERRIDE)) |
1145 | return 0; | 1145 | return 0; |
1146 | 1146 | ||
1147 | return rc; | 1147 | return rc; |
1148 | } | 1148 | } |
1149 | 1149 | ||
1150 | /** | 1150 | /** |
1151 | * smack_task_to_inode - copy task smack into the inode blob | 1151 | * smack_task_to_inode - copy task smack into the inode blob |
1152 | * @p: task to copy from | 1152 | * @p: task to copy from |
1153 | * inode: inode to copy to | 1153 | * inode: inode to copy to |
1154 | * | 1154 | * |
1155 | * Sets the smack pointer in the inode security blob | 1155 | * Sets the smack pointer in the inode security blob |
1156 | */ | 1156 | */ |
1157 | static void smack_task_to_inode(struct task_struct *p, struct inode *inode) | 1157 | static void smack_task_to_inode(struct task_struct *p, struct inode *inode) |
1158 | { | 1158 | { |
1159 | struct inode_smack *isp = inode->i_security; | 1159 | struct inode_smack *isp = inode->i_security; |
1160 | isp->smk_inode = p->security; | 1160 | isp->smk_inode = p->security; |
1161 | } | 1161 | } |
1162 | 1162 | ||
1163 | /* | 1163 | /* |
1164 | * Socket hooks. | 1164 | * Socket hooks. |
1165 | */ | 1165 | */ |
1166 | 1166 | ||
1167 | /** | 1167 | /** |
1168 | * smack_sk_alloc_security - Allocate a socket blob | 1168 | * smack_sk_alloc_security - Allocate a socket blob |
1169 | * @sk: the socket | 1169 | * @sk: the socket |
1170 | * @family: unused | 1170 | * @family: unused |
1171 | * @priority: memory allocation priority | 1171 | * @priority: memory allocation priority |
1172 | * | 1172 | * |
1173 | * Assign Smack pointers to current | 1173 | * Assign Smack pointers to current |
1174 | * | 1174 | * |
1175 | * Returns 0 on success, -ENOMEM is there's no memory | 1175 | * Returns 0 on success, -ENOMEM is there's no memory |
1176 | */ | 1176 | */ |
1177 | static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags) | 1177 | static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags) |
1178 | { | 1178 | { |
1179 | char *csp = current->security; | 1179 | char *csp = current->security; |
1180 | struct socket_smack *ssp; | 1180 | struct socket_smack *ssp; |
1181 | 1181 | ||
1182 | ssp = kzalloc(sizeof(struct socket_smack), gfp_flags); | 1182 | ssp = kzalloc(sizeof(struct socket_smack), gfp_flags); |
1183 | if (ssp == NULL) | 1183 | if (ssp == NULL) |
1184 | return -ENOMEM; | 1184 | return -ENOMEM; |
1185 | 1185 | ||
1186 | ssp->smk_in = csp; | 1186 | ssp->smk_in = csp; |
1187 | ssp->smk_out = csp; | 1187 | ssp->smk_out = csp; |
1188 | ssp->smk_packet[0] = '\0'; | 1188 | ssp->smk_packet[0] = '\0'; |
1189 | 1189 | ||
1190 | sk->sk_security = ssp; | 1190 | sk->sk_security = ssp; |
1191 | 1191 | ||
1192 | return 0; | 1192 | return 0; |
1193 | } | 1193 | } |
1194 | 1194 | ||
1195 | /** | 1195 | /** |
1196 | * smack_sk_free_security - Free a socket blob | 1196 | * smack_sk_free_security - Free a socket blob |
1197 | * @sk: the socket | 1197 | * @sk: the socket |
1198 | * | 1198 | * |
1199 | * Clears the blob pointer | 1199 | * Clears the blob pointer |
1200 | */ | 1200 | */ |
1201 | static void smack_sk_free_security(struct sock *sk) | 1201 | static void smack_sk_free_security(struct sock *sk) |
1202 | { | 1202 | { |
1203 | kfree(sk->sk_security); | 1203 | kfree(sk->sk_security); |
1204 | } | 1204 | } |
1205 | 1205 | ||
1206 | /** | 1206 | /** |
1207 | * smack_set_catset - convert a capset to netlabel mls categories | 1207 | * smack_set_catset - convert a capset to netlabel mls categories |
1208 | * @catset: the Smack categories | 1208 | * @catset: the Smack categories |
1209 | * @sap: where to put the netlabel categories | 1209 | * @sap: where to put the netlabel categories |
1210 | * | 1210 | * |
1211 | * Allocates and fills attr.mls.cat | 1211 | * Allocates and fills attr.mls.cat |
1212 | */ | 1212 | */ |
1213 | static void smack_set_catset(char *catset, struct netlbl_lsm_secattr *sap) | 1213 | static void smack_set_catset(char *catset, struct netlbl_lsm_secattr *sap) |
1214 | { | 1214 | { |
1215 | unsigned char *cp; | 1215 | unsigned char *cp; |
1216 | unsigned char m; | 1216 | unsigned char m; |
1217 | int cat; | 1217 | int cat; |
1218 | int rc; | 1218 | int rc; |
1219 | int byte; | 1219 | int byte; |
1220 | 1220 | ||
1221 | if (catset == 0) | 1221 | if (catset == 0) |
1222 | return; | 1222 | return; |
1223 | 1223 | ||
1224 | sap->flags |= NETLBL_SECATTR_MLS_CAT; | 1224 | sap->flags |= NETLBL_SECATTR_MLS_CAT; |
1225 | sap->attr.mls.cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC); | 1225 | sap->attr.mls.cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC); |
1226 | sap->attr.mls.cat->startbit = 0; | 1226 | sap->attr.mls.cat->startbit = 0; |
1227 | 1227 | ||
1228 | for (cat = 1, cp = catset, byte = 0; byte < SMK_LABELLEN; cp++, byte++) | 1228 | for (cat = 1, cp = catset, byte = 0; byte < SMK_LABELLEN; cp++, byte++) |
1229 | for (m = 0x80; m != 0; m >>= 1, cat++) { | 1229 | for (m = 0x80; m != 0; m >>= 1, cat++) { |
1230 | if ((m & *cp) == 0) | 1230 | if ((m & *cp) == 0) |
1231 | continue; | 1231 | continue; |
1232 | rc = netlbl_secattr_catmap_setbit(sap->attr.mls.cat, | 1232 | rc = netlbl_secattr_catmap_setbit(sap->attr.mls.cat, |
1233 | cat, GFP_ATOMIC); | 1233 | cat, GFP_ATOMIC); |
1234 | } | 1234 | } |
1235 | } | 1235 | } |
1236 | 1236 | ||
1237 | /** | 1237 | /** |
1238 | * smack_to_secattr - fill a secattr from a smack value | 1238 | * smack_to_secattr - fill a secattr from a smack value |
1239 | * @smack: the smack value | 1239 | * @smack: the smack value |
1240 | * @nlsp: where the result goes | 1240 | * @nlsp: where the result goes |
1241 | * | 1241 | * |
1242 | * Casey says that CIPSO is good enough for now. | 1242 | * Casey says that CIPSO is good enough for now. |
1243 | * It can be used to effect. | 1243 | * It can be used to effect. |
1244 | * It can also be abused to effect when necessary. | 1244 | * It can also be abused to effect when necessary. |
1245 | * Appologies to the TSIG group in general and GW in particular. | 1245 | * Appologies to the TSIG group in general and GW in particular. |
1246 | */ | 1246 | */ |
1247 | static void smack_to_secattr(char *smack, struct netlbl_lsm_secattr *nlsp) | 1247 | static void smack_to_secattr(char *smack, struct netlbl_lsm_secattr *nlsp) |
1248 | { | 1248 | { |
1249 | struct smack_cipso cipso; | 1249 | struct smack_cipso cipso; |
1250 | int rc; | 1250 | int rc; |
1251 | 1251 | ||
1252 | switch (smack_net_nltype) { | 1252 | switch (smack_net_nltype) { |
1253 | case NETLBL_NLTYPE_CIPSOV4: | 1253 | case NETLBL_NLTYPE_CIPSOV4: |
1254 | nlsp->domain = NULL; | 1254 | nlsp->domain = kstrdup(smack, GFP_ATOMIC); |
1255 | nlsp->flags = NETLBL_SECATTR_DOMAIN; | 1255 | nlsp->flags = NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL; |
1256 | nlsp->flags |= NETLBL_SECATTR_MLS_LVL; | ||
1257 | 1256 | ||
1258 | rc = smack_to_cipso(smack, &cipso); | 1257 | rc = smack_to_cipso(smack, &cipso); |
1259 | if (rc == 0) { | 1258 | if (rc == 0) { |
1260 | nlsp->attr.mls.lvl = cipso.smk_level; | 1259 | nlsp->attr.mls.lvl = cipso.smk_level; |
1261 | smack_set_catset(cipso.smk_catset, nlsp); | 1260 | smack_set_catset(cipso.smk_catset, nlsp); |
1262 | } else { | 1261 | } else { |
1263 | nlsp->attr.mls.lvl = smack_cipso_direct; | 1262 | nlsp->attr.mls.lvl = smack_cipso_direct; |
1264 | smack_set_catset(smack, nlsp); | 1263 | smack_set_catset(smack, nlsp); |
1265 | } | 1264 | } |
1266 | break; | 1265 | break; |
1267 | default: | 1266 | default: |
1268 | break; | 1267 | break; |
1269 | } | 1268 | } |
1270 | } | 1269 | } |
1271 | 1270 | ||
1272 | /** | 1271 | /** |
1273 | * smack_netlabel - Set the secattr on a socket | 1272 | * smack_netlabel - Set the secattr on a socket |
1274 | * @sk: the socket | 1273 | * @sk: the socket |
1275 | * | 1274 | * |
1276 | * Convert the outbound smack value (smk_out) to a | 1275 | * Convert the outbound smack value (smk_out) to a |
1277 | * secattr and attach it to the socket. | 1276 | * secattr and attach it to the socket. |
1278 | * | 1277 | * |
1279 | * Returns 0 on success or an error code | 1278 | * Returns 0 on success or an error code |
1280 | */ | 1279 | */ |
1281 | static int smack_netlabel(struct sock *sk) | 1280 | static int smack_netlabel(struct sock *sk) |
1282 | { | 1281 | { |
1283 | struct socket_smack *ssp; | 1282 | struct socket_smack *ssp; |
1284 | struct netlbl_lsm_secattr secattr; | 1283 | struct netlbl_lsm_secattr secattr; |
1285 | int rc = 0; | 1284 | int rc; |
1286 | 1285 | ||
1287 | ssp = sk->sk_security; | 1286 | ssp = sk->sk_security; |
1288 | netlbl_secattr_init(&secattr); | 1287 | netlbl_secattr_init(&secattr); |
1289 | smack_to_secattr(ssp->smk_out, &secattr); | 1288 | smack_to_secattr(ssp->smk_out, &secattr); |
1290 | if (secattr.flags != NETLBL_SECATTR_NONE) | 1289 | rc = netlbl_sock_setattr(sk, &secattr); |
1291 | rc = netlbl_sock_setattr(sk, &secattr); | ||
1292 | |||
1293 | netlbl_secattr_destroy(&secattr); | 1290 | netlbl_secattr_destroy(&secattr); |
1291 | |||
1294 | return rc; | 1292 | return rc; |
1295 | } | 1293 | } |
1296 | 1294 | ||
1297 | /** | 1295 | /** |
1298 | * smack_inode_setsecurity - set smack xattrs | 1296 | * smack_inode_setsecurity - set smack xattrs |
1299 | * @inode: the object | 1297 | * @inode: the object |
1300 | * @name: attribute name | 1298 | * @name: attribute name |
1301 | * @value: attribute value | 1299 | * @value: attribute value |
1302 | * @size: size of the attribute | 1300 | * @size: size of the attribute |
1303 | * @flags: unused | 1301 | * @flags: unused |
1304 | * | 1302 | * |
1305 | * Sets the named attribute in the appropriate blob | 1303 | * Sets the named attribute in the appropriate blob |
1306 | * | 1304 | * |
1307 | * Returns 0 on success, or an error code | 1305 | * Returns 0 on success, or an error code |
1308 | */ | 1306 | */ |
1309 | static int smack_inode_setsecurity(struct inode *inode, const char *name, | 1307 | static int smack_inode_setsecurity(struct inode *inode, const char *name, |
1310 | const void *value, size_t size, int flags) | 1308 | const void *value, size_t size, int flags) |
1311 | { | 1309 | { |
1312 | char *sp; | 1310 | char *sp; |
1313 | struct inode_smack *nsp = inode->i_security; | 1311 | struct inode_smack *nsp = inode->i_security; |
1314 | struct socket_smack *ssp; | 1312 | struct socket_smack *ssp; |
1315 | struct socket *sock; | 1313 | struct socket *sock; |
1314 | int rc = 0; | ||
1316 | 1315 | ||
1317 | if (value == NULL || size > SMK_LABELLEN) | 1316 | if (value == NULL || size > SMK_LABELLEN) |
1318 | return -EACCES; | 1317 | return -EACCES; |
1319 | 1318 | ||
1320 | sp = smk_import(value, size); | 1319 | sp = smk_import(value, size); |
1321 | if (sp == NULL) | 1320 | if (sp == NULL) |
1322 | return -EINVAL; | 1321 | return -EINVAL; |
1323 | 1322 | ||
1324 | if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) { | 1323 | if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) { |
1325 | nsp->smk_inode = sp; | 1324 | nsp->smk_inode = sp; |
1326 | return 0; | 1325 | return 0; |
1327 | } | 1326 | } |
1328 | /* | 1327 | /* |
1329 | * The rest of the Smack xattrs are only on sockets. | 1328 | * The rest of the Smack xattrs are only on sockets. |
1330 | */ | 1329 | */ |
1331 | if (inode->i_sb->s_magic != SOCKFS_MAGIC) | 1330 | if (inode->i_sb->s_magic != SOCKFS_MAGIC) |
1332 | return -EOPNOTSUPP; | 1331 | return -EOPNOTSUPP; |
1333 | 1332 | ||
1334 | sock = SOCKET_I(inode); | 1333 | sock = SOCKET_I(inode); |
1335 | if (sock == NULL || sock->sk == NULL) | 1334 | if (sock == NULL || sock->sk == NULL) |
1336 | return -EOPNOTSUPP; | 1335 | return -EOPNOTSUPP; |
1337 | 1336 | ||
1338 | ssp = sock->sk->sk_security; | 1337 | ssp = sock->sk->sk_security; |
1339 | 1338 | ||
1340 | if (strcmp(name, XATTR_SMACK_IPIN) == 0) | 1339 | if (strcmp(name, XATTR_SMACK_IPIN) == 0) |
1341 | ssp->smk_in = sp; | 1340 | ssp->smk_in = sp; |
1342 | else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) { | 1341 | else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) { |
1343 | ssp->smk_out = sp; | 1342 | ssp->smk_out = sp; |
1344 | return smack_netlabel(sock->sk); | 1343 | rc = smack_netlabel(sock->sk); |
1344 | if (rc != 0) | ||
1345 | printk(KERN_WARNING "Smack: \"%s\" netlbl error %d.\n", | ||
1346 | __func__, -rc); | ||
1345 | } else | 1347 | } else |
1346 | return -EOPNOTSUPP; | 1348 | return -EOPNOTSUPP; |
1347 | 1349 | ||
1348 | return 0; | 1350 | return 0; |
1349 | } | 1351 | } |
1350 | 1352 | ||
1351 | /** | 1353 | /** |
1352 | * smack_socket_post_create - finish socket setup | 1354 | * smack_socket_post_create - finish socket setup |
1353 | * @sock: the socket | 1355 | * @sock: the socket |
1354 | * @family: protocol family | 1356 | * @family: protocol family |
1355 | * @type: unused | 1357 | * @type: unused |
1356 | * @protocol: unused | 1358 | * @protocol: unused |
1357 | * @kern: unused | 1359 | * @kern: unused |
1358 | * | 1360 | * |
1359 | * Sets the netlabel information on the socket | 1361 | * Sets the netlabel information on the socket |
1360 | * | 1362 | * |
1361 | * Returns 0 on success, and error code otherwise | 1363 | * Returns 0 on success, and error code otherwise |
1362 | */ | 1364 | */ |
1363 | static int smack_socket_post_create(struct socket *sock, int family, | 1365 | static int smack_socket_post_create(struct socket *sock, int family, |
1364 | int type, int protocol, int kern) | 1366 | int type, int protocol, int kern) |
1365 | { | 1367 | { |
1366 | if (family != PF_INET || sock->sk == NULL) | 1368 | if (family != PF_INET || sock->sk == NULL) |
1367 | return 0; | 1369 | return 0; |
1368 | /* | 1370 | /* |
1369 | * Set the outbound netlbl. | 1371 | * Set the outbound netlbl. |
1370 | */ | 1372 | */ |
1371 | return smack_netlabel(sock->sk); | 1373 | return smack_netlabel(sock->sk); |
1372 | } | 1374 | } |
1373 | 1375 | ||
1374 | /** | 1376 | /** |
1375 | * smack_flags_to_may - convert S_ to MAY_ values | 1377 | * smack_flags_to_may - convert S_ to MAY_ values |
1376 | * @flags: the S_ value | 1378 | * @flags: the S_ value |
1377 | * | 1379 | * |
1378 | * Returns the equivalent MAY_ value | 1380 | * Returns the equivalent MAY_ value |
1379 | */ | 1381 | */ |
1380 | static int smack_flags_to_may(int flags) | 1382 | static int smack_flags_to_may(int flags) |
1381 | { | 1383 | { |
1382 | int may = 0; | 1384 | int may = 0; |
1383 | 1385 | ||
1384 | if (flags & S_IRUGO) | 1386 | if (flags & S_IRUGO) |
1385 | may |= MAY_READ; | 1387 | may |= MAY_READ; |
1386 | if (flags & S_IWUGO) | 1388 | if (flags & S_IWUGO) |
1387 | may |= MAY_WRITE; | 1389 | may |= MAY_WRITE; |
1388 | if (flags & S_IXUGO) | 1390 | if (flags & S_IXUGO) |
1389 | may |= MAY_EXEC; | 1391 | may |= MAY_EXEC; |
1390 | 1392 | ||
1391 | return may; | 1393 | return may; |
1392 | } | 1394 | } |
1393 | 1395 | ||
1394 | /** | 1396 | /** |
1395 | * smack_msg_msg_alloc_security - Set the security blob for msg_msg | 1397 | * smack_msg_msg_alloc_security - Set the security blob for msg_msg |
1396 | * @msg: the object | 1398 | * @msg: the object |
1397 | * | 1399 | * |
1398 | * Returns 0 | 1400 | * Returns 0 |
1399 | */ | 1401 | */ |
1400 | static int smack_msg_msg_alloc_security(struct msg_msg *msg) | 1402 | static int smack_msg_msg_alloc_security(struct msg_msg *msg) |
1401 | { | 1403 | { |
1402 | msg->security = current->security; | 1404 | msg->security = current->security; |
1403 | return 0; | 1405 | return 0; |
1404 | } | 1406 | } |
1405 | 1407 | ||
1406 | /** | 1408 | /** |
1407 | * smack_msg_msg_free_security - Clear the security blob for msg_msg | 1409 | * smack_msg_msg_free_security - Clear the security blob for msg_msg |
1408 | * @msg: the object | 1410 | * @msg: the object |
1409 | * | 1411 | * |
1410 | * Clears the blob pointer | 1412 | * Clears the blob pointer |
1411 | */ | 1413 | */ |
1412 | static void smack_msg_msg_free_security(struct msg_msg *msg) | 1414 | static void smack_msg_msg_free_security(struct msg_msg *msg) |
1413 | { | 1415 | { |
1414 | msg->security = NULL; | 1416 | msg->security = NULL; |
1415 | } | 1417 | } |
1416 | 1418 | ||
1417 | /** | 1419 | /** |
1418 | * smack_of_shm - the smack pointer for the shm | 1420 | * smack_of_shm - the smack pointer for the shm |
1419 | * @shp: the object | 1421 | * @shp: the object |
1420 | * | 1422 | * |
1421 | * Returns a pointer to the smack value | 1423 | * Returns a pointer to the smack value |
1422 | */ | 1424 | */ |
1423 | static char *smack_of_shm(struct shmid_kernel *shp) | 1425 | static char *smack_of_shm(struct shmid_kernel *shp) |
1424 | { | 1426 | { |
1425 | return (char *)shp->shm_perm.security; | 1427 | return (char *)shp->shm_perm.security; |
1426 | } | 1428 | } |
1427 | 1429 | ||
1428 | /** | 1430 | /** |
1429 | * smack_shm_alloc_security - Set the security blob for shm | 1431 | * smack_shm_alloc_security - Set the security blob for shm |
1430 | * @shp: the object | 1432 | * @shp: the object |
1431 | * | 1433 | * |
1432 | * Returns 0 | 1434 | * Returns 0 |
1433 | */ | 1435 | */ |
1434 | static int smack_shm_alloc_security(struct shmid_kernel *shp) | 1436 | static int smack_shm_alloc_security(struct shmid_kernel *shp) |
1435 | { | 1437 | { |
1436 | struct kern_ipc_perm *isp = &shp->shm_perm; | 1438 | struct kern_ipc_perm *isp = &shp->shm_perm; |
1437 | 1439 | ||
1438 | isp->security = current->security; | 1440 | isp->security = current->security; |
1439 | return 0; | 1441 | return 0; |
1440 | } | 1442 | } |
1441 | 1443 | ||
1442 | /** | 1444 | /** |
1443 | * smack_shm_free_security - Clear the security blob for shm | 1445 | * smack_shm_free_security - Clear the security blob for shm |
1444 | * @shp: the object | 1446 | * @shp: the object |
1445 | * | 1447 | * |
1446 | * Clears the blob pointer | 1448 | * Clears the blob pointer |
1447 | */ | 1449 | */ |
1448 | static void smack_shm_free_security(struct shmid_kernel *shp) | 1450 | static void smack_shm_free_security(struct shmid_kernel *shp) |
1449 | { | 1451 | { |
1450 | struct kern_ipc_perm *isp = &shp->shm_perm; | 1452 | struct kern_ipc_perm *isp = &shp->shm_perm; |
1451 | 1453 | ||
1452 | isp->security = NULL; | 1454 | isp->security = NULL; |
1453 | } | 1455 | } |
1454 | 1456 | ||
1455 | /** | 1457 | /** |
1456 | * smack_shm_associate - Smack access check for shm | 1458 | * smack_shm_associate - Smack access check for shm |
1457 | * @shp: the object | 1459 | * @shp: the object |
1458 | * @shmflg: access requested | 1460 | * @shmflg: access requested |
1459 | * | 1461 | * |
1460 | * Returns 0 if current has the requested access, error code otherwise | 1462 | * Returns 0 if current has the requested access, error code otherwise |
1461 | */ | 1463 | */ |
1462 | static int smack_shm_associate(struct shmid_kernel *shp, int shmflg) | 1464 | static int smack_shm_associate(struct shmid_kernel *shp, int shmflg) |
1463 | { | 1465 | { |
1464 | char *ssp = smack_of_shm(shp); | 1466 | char *ssp = smack_of_shm(shp); |
1465 | int may; | 1467 | int may; |
1466 | 1468 | ||
1467 | may = smack_flags_to_may(shmflg); | 1469 | may = smack_flags_to_may(shmflg); |
1468 | return smk_curacc(ssp, may); | 1470 | return smk_curacc(ssp, may); |
1469 | } | 1471 | } |
1470 | 1472 | ||
1471 | /** | 1473 | /** |
1472 | * smack_shm_shmctl - Smack access check for shm | 1474 | * smack_shm_shmctl - Smack access check for shm |
1473 | * @shp: the object | 1475 | * @shp: the object |
1474 | * @cmd: what it wants to do | 1476 | * @cmd: what it wants to do |
1475 | * | 1477 | * |
1476 | * Returns 0 if current has the requested access, error code otherwise | 1478 | * Returns 0 if current has the requested access, error code otherwise |
1477 | */ | 1479 | */ |
1478 | static int smack_shm_shmctl(struct shmid_kernel *shp, int cmd) | 1480 | static int smack_shm_shmctl(struct shmid_kernel *shp, int cmd) |
1479 | { | 1481 | { |
1480 | char *ssp = smack_of_shm(shp); | 1482 | char *ssp = smack_of_shm(shp); |
1481 | int may; | 1483 | int may; |
1482 | 1484 | ||
1483 | switch (cmd) { | 1485 | switch (cmd) { |
1484 | case IPC_STAT: | 1486 | case IPC_STAT: |
1485 | case SHM_STAT: | 1487 | case SHM_STAT: |
1486 | may = MAY_READ; | 1488 | may = MAY_READ; |
1487 | break; | 1489 | break; |
1488 | case IPC_SET: | 1490 | case IPC_SET: |
1489 | case SHM_LOCK: | 1491 | case SHM_LOCK: |
1490 | case SHM_UNLOCK: | 1492 | case SHM_UNLOCK: |
1491 | case IPC_RMID: | 1493 | case IPC_RMID: |
1492 | may = MAY_READWRITE; | 1494 | may = MAY_READWRITE; |
1493 | break; | 1495 | break; |
1494 | case IPC_INFO: | 1496 | case IPC_INFO: |
1495 | case SHM_INFO: | 1497 | case SHM_INFO: |
1496 | /* | 1498 | /* |
1497 | * System level information. | 1499 | * System level information. |
1498 | */ | 1500 | */ |
1499 | return 0; | 1501 | return 0; |
1500 | default: | 1502 | default: |
1501 | return -EINVAL; | 1503 | return -EINVAL; |
1502 | } | 1504 | } |
1503 | 1505 | ||
1504 | return smk_curacc(ssp, may); | 1506 | return smk_curacc(ssp, may); |
1505 | } | 1507 | } |
1506 | 1508 | ||
1507 | /** | 1509 | /** |
1508 | * smack_shm_shmat - Smack access for shmat | 1510 | * smack_shm_shmat - Smack access for shmat |
1509 | * @shp: the object | 1511 | * @shp: the object |
1510 | * @shmaddr: unused | 1512 | * @shmaddr: unused |
1511 | * @shmflg: access requested | 1513 | * @shmflg: access requested |
1512 | * | 1514 | * |
1513 | * Returns 0 if current has the requested access, error code otherwise | 1515 | * Returns 0 if current has the requested access, error code otherwise |
1514 | */ | 1516 | */ |
1515 | static int smack_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr, | 1517 | static int smack_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr, |
1516 | int shmflg) | 1518 | int shmflg) |
1517 | { | 1519 | { |
1518 | char *ssp = smack_of_shm(shp); | 1520 | char *ssp = smack_of_shm(shp); |
1519 | int may; | 1521 | int may; |
1520 | 1522 | ||
1521 | may = smack_flags_to_may(shmflg); | 1523 | may = smack_flags_to_may(shmflg); |
1522 | return smk_curacc(ssp, may); | 1524 | return smk_curacc(ssp, may); |
1523 | } | 1525 | } |
1524 | 1526 | ||
1525 | /** | 1527 | /** |
1526 | * smack_of_sem - the smack pointer for the sem | 1528 | * smack_of_sem - the smack pointer for the sem |
1527 | * @sma: the object | 1529 | * @sma: the object |
1528 | * | 1530 | * |
1529 | * Returns a pointer to the smack value | 1531 | * Returns a pointer to the smack value |
1530 | */ | 1532 | */ |
1531 | static char *smack_of_sem(struct sem_array *sma) | 1533 | static char *smack_of_sem(struct sem_array *sma) |
1532 | { | 1534 | { |
1533 | return (char *)sma->sem_perm.security; | 1535 | return (char *)sma->sem_perm.security; |
1534 | } | 1536 | } |
1535 | 1537 | ||
1536 | /** | 1538 | /** |
1537 | * smack_sem_alloc_security - Set the security blob for sem | 1539 | * smack_sem_alloc_security - Set the security blob for sem |
1538 | * @sma: the object | 1540 | * @sma: the object |
1539 | * | 1541 | * |
1540 | * Returns 0 | 1542 | * Returns 0 |
1541 | */ | 1543 | */ |
1542 | static int smack_sem_alloc_security(struct sem_array *sma) | 1544 | static int smack_sem_alloc_security(struct sem_array *sma) |
1543 | { | 1545 | { |
1544 | struct kern_ipc_perm *isp = &sma->sem_perm; | 1546 | struct kern_ipc_perm *isp = &sma->sem_perm; |
1545 | 1547 | ||
1546 | isp->security = current->security; | 1548 | isp->security = current->security; |
1547 | return 0; | 1549 | return 0; |
1548 | } | 1550 | } |
1549 | 1551 | ||
1550 | /** | 1552 | /** |
1551 | * smack_sem_free_security - Clear the security blob for sem | 1553 | * smack_sem_free_security - Clear the security blob for sem |
1552 | * @sma: the object | 1554 | * @sma: the object |
1553 | * | 1555 | * |
1554 | * Clears the blob pointer | 1556 | * Clears the blob pointer |
1555 | */ | 1557 | */ |
1556 | static void smack_sem_free_security(struct sem_array *sma) | 1558 | static void smack_sem_free_security(struct sem_array *sma) |
1557 | { | 1559 | { |
1558 | struct kern_ipc_perm *isp = &sma->sem_perm; | 1560 | struct kern_ipc_perm *isp = &sma->sem_perm; |
1559 | 1561 | ||
1560 | isp->security = NULL; | 1562 | isp->security = NULL; |
1561 | } | 1563 | } |
1562 | 1564 | ||
1563 | /** | 1565 | /** |
1564 | * smack_sem_associate - Smack access check for sem | 1566 | * smack_sem_associate - Smack access check for sem |
1565 | * @sma: the object | 1567 | * @sma: the object |
1566 | * @semflg: access requested | 1568 | * @semflg: access requested |
1567 | * | 1569 | * |
1568 | * Returns 0 if current has the requested access, error code otherwise | 1570 | * Returns 0 if current has the requested access, error code otherwise |
1569 | */ | 1571 | */ |
1570 | static int smack_sem_associate(struct sem_array *sma, int semflg) | 1572 | static int smack_sem_associate(struct sem_array *sma, int semflg) |
1571 | { | 1573 | { |
1572 | char *ssp = smack_of_sem(sma); | 1574 | char *ssp = smack_of_sem(sma); |
1573 | int may; | 1575 | int may; |
1574 | 1576 | ||
1575 | may = smack_flags_to_may(semflg); | 1577 | may = smack_flags_to_may(semflg); |
1576 | return smk_curacc(ssp, may); | 1578 | return smk_curacc(ssp, may); |
1577 | } | 1579 | } |
1578 | 1580 | ||
1579 | /** | 1581 | /** |
1580 | * smack_sem_shmctl - Smack access check for sem | 1582 | * smack_sem_shmctl - Smack access check for sem |
1581 | * @sma: the object | 1583 | * @sma: the object |
1582 | * @cmd: what it wants to do | 1584 | * @cmd: what it wants to do |
1583 | * | 1585 | * |
1584 | * Returns 0 if current has the requested access, error code otherwise | 1586 | * Returns 0 if current has the requested access, error code otherwise |
1585 | */ | 1587 | */ |
1586 | static int smack_sem_semctl(struct sem_array *sma, int cmd) | 1588 | static int smack_sem_semctl(struct sem_array *sma, int cmd) |
1587 | { | 1589 | { |
1588 | char *ssp = smack_of_sem(sma); | 1590 | char *ssp = smack_of_sem(sma); |
1589 | int may; | 1591 | int may; |
1590 | 1592 | ||
1591 | switch (cmd) { | 1593 | switch (cmd) { |
1592 | case GETPID: | 1594 | case GETPID: |
1593 | case GETNCNT: | 1595 | case GETNCNT: |
1594 | case GETZCNT: | 1596 | case GETZCNT: |
1595 | case GETVAL: | 1597 | case GETVAL: |
1596 | case GETALL: | 1598 | case GETALL: |
1597 | case IPC_STAT: | 1599 | case IPC_STAT: |
1598 | case SEM_STAT: | 1600 | case SEM_STAT: |
1599 | may = MAY_READ; | 1601 | may = MAY_READ; |
1600 | break; | 1602 | break; |
1601 | case SETVAL: | 1603 | case SETVAL: |
1602 | case SETALL: | 1604 | case SETALL: |
1603 | case IPC_RMID: | 1605 | case IPC_RMID: |
1604 | case IPC_SET: | 1606 | case IPC_SET: |
1605 | may = MAY_READWRITE; | 1607 | may = MAY_READWRITE; |
1606 | break; | 1608 | break; |
1607 | case IPC_INFO: | 1609 | case IPC_INFO: |
1608 | case SEM_INFO: | 1610 | case SEM_INFO: |
1609 | /* | 1611 | /* |
1610 | * System level information | 1612 | * System level information |
1611 | */ | 1613 | */ |
1612 | return 0; | 1614 | return 0; |
1613 | default: | 1615 | default: |
1614 | return -EINVAL; | 1616 | return -EINVAL; |
1615 | } | 1617 | } |
1616 | 1618 | ||
1617 | return smk_curacc(ssp, may); | 1619 | return smk_curacc(ssp, may); |
1618 | } | 1620 | } |
1619 | 1621 | ||
1620 | /** | 1622 | /** |
1621 | * smack_sem_semop - Smack checks of semaphore operations | 1623 | * smack_sem_semop - Smack checks of semaphore operations |
1622 | * @sma: the object | 1624 | * @sma: the object |
1623 | * @sops: unused | 1625 | * @sops: unused |
1624 | * @nsops: unused | 1626 | * @nsops: unused |
1625 | * @alter: unused | 1627 | * @alter: unused |
1626 | * | 1628 | * |
1627 | * Treated as read and write in all cases. | 1629 | * Treated as read and write in all cases. |
1628 | * | 1630 | * |
1629 | * Returns 0 if access is allowed, error code otherwise | 1631 | * Returns 0 if access is allowed, error code otherwise |
1630 | */ | 1632 | */ |
1631 | static int smack_sem_semop(struct sem_array *sma, struct sembuf *sops, | 1633 | static int smack_sem_semop(struct sem_array *sma, struct sembuf *sops, |
1632 | unsigned nsops, int alter) | 1634 | unsigned nsops, int alter) |
1633 | { | 1635 | { |
1634 | char *ssp = smack_of_sem(sma); | 1636 | char *ssp = smack_of_sem(sma); |
1635 | 1637 | ||
1636 | return smk_curacc(ssp, MAY_READWRITE); | 1638 | return smk_curacc(ssp, MAY_READWRITE); |
1637 | } | 1639 | } |
1638 | 1640 | ||
1639 | /** | 1641 | /** |
1640 | * smack_msg_alloc_security - Set the security blob for msg | 1642 | * smack_msg_alloc_security - Set the security blob for msg |
1641 | * @msq: the object | 1643 | * @msq: the object |
1642 | * | 1644 | * |
1643 | * Returns 0 | 1645 | * Returns 0 |
1644 | */ | 1646 | */ |
1645 | static int smack_msg_queue_alloc_security(struct msg_queue *msq) | 1647 | static int smack_msg_queue_alloc_security(struct msg_queue *msq) |
1646 | { | 1648 | { |
1647 | struct kern_ipc_perm *kisp = &msq->q_perm; | 1649 | struct kern_ipc_perm *kisp = &msq->q_perm; |
1648 | 1650 | ||
1649 | kisp->security = current->security; | 1651 | kisp->security = current->security; |
1650 | return 0; | 1652 | return 0; |
1651 | } | 1653 | } |
1652 | 1654 | ||
1653 | /** | 1655 | /** |
1654 | * smack_msg_free_security - Clear the security blob for msg | 1656 | * smack_msg_free_security - Clear the security blob for msg |
1655 | * @msq: the object | 1657 | * @msq: the object |
1656 | * | 1658 | * |
1657 | * Clears the blob pointer | 1659 | * Clears the blob pointer |
1658 | */ | 1660 | */ |
1659 | static void smack_msg_queue_free_security(struct msg_queue *msq) | 1661 | static void smack_msg_queue_free_security(struct msg_queue *msq) |
1660 | { | 1662 | { |
1661 | struct kern_ipc_perm *kisp = &msq->q_perm; | 1663 | struct kern_ipc_perm *kisp = &msq->q_perm; |
1662 | 1664 | ||
1663 | kisp->security = NULL; | 1665 | kisp->security = NULL; |
1664 | } | 1666 | } |
1665 | 1667 | ||
1666 | /** | 1668 | /** |
1667 | * smack_of_msq - the smack pointer for the msq | 1669 | * smack_of_msq - the smack pointer for the msq |
1668 | * @msq: the object | 1670 | * @msq: the object |
1669 | * | 1671 | * |
1670 | * Returns a pointer to the smack value | 1672 | * Returns a pointer to the smack value |
1671 | */ | 1673 | */ |
1672 | static char *smack_of_msq(struct msg_queue *msq) | 1674 | static char *smack_of_msq(struct msg_queue *msq) |
1673 | { | 1675 | { |
1674 | return (char *)msq->q_perm.security; | 1676 | return (char *)msq->q_perm.security; |
1675 | } | 1677 | } |
1676 | 1678 | ||
1677 | /** | 1679 | /** |
1678 | * smack_msg_queue_associate - Smack access check for msg_queue | 1680 | * smack_msg_queue_associate - Smack access check for msg_queue |
1679 | * @msq: the object | 1681 | * @msq: the object |
1680 | * @msqflg: access requested | 1682 | * @msqflg: access requested |
1681 | * | 1683 | * |
1682 | * Returns 0 if current has the requested access, error code otherwise | 1684 | * Returns 0 if current has the requested access, error code otherwise |
1683 | */ | 1685 | */ |
1684 | static int smack_msg_queue_associate(struct msg_queue *msq, int msqflg) | 1686 | static int smack_msg_queue_associate(struct msg_queue *msq, int msqflg) |
1685 | { | 1687 | { |
1686 | char *msp = smack_of_msq(msq); | 1688 | char *msp = smack_of_msq(msq); |
1687 | int may; | 1689 | int may; |
1688 | 1690 | ||
1689 | may = smack_flags_to_may(msqflg); | 1691 | may = smack_flags_to_may(msqflg); |
1690 | return smk_curacc(msp, may); | 1692 | return smk_curacc(msp, may); |
1691 | } | 1693 | } |
1692 | 1694 | ||
1693 | /** | 1695 | /** |
1694 | * smack_msg_queue_msgctl - Smack access check for msg_queue | 1696 | * smack_msg_queue_msgctl - Smack access check for msg_queue |
1695 | * @msq: the object | 1697 | * @msq: the object |
1696 | * @cmd: what it wants to do | 1698 | * @cmd: what it wants to do |
1697 | * | 1699 | * |
1698 | * Returns 0 if current has the requested access, error code otherwise | 1700 | * Returns 0 if current has the requested access, error code otherwise |
1699 | */ | 1701 | */ |
1700 | static int smack_msg_queue_msgctl(struct msg_queue *msq, int cmd) | 1702 | static int smack_msg_queue_msgctl(struct msg_queue *msq, int cmd) |
1701 | { | 1703 | { |
1702 | char *msp = smack_of_msq(msq); | 1704 | char *msp = smack_of_msq(msq); |
1703 | int may; | 1705 | int may; |
1704 | 1706 | ||
1705 | switch (cmd) { | 1707 | switch (cmd) { |
1706 | case IPC_STAT: | 1708 | case IPC_STAT: |
1707 | case MSG_STAT: | 1709 | case MSG_STAT: |
1708 | may = MAY_READ; | 1710 | may = MAY_READ; |
1709 | break; | 1711 | break; |
1710 | case IPC_SET: | 1712 | case IPC_SET: |
1711 | case IPC_RMID: | 1713 | case IPC_RMID: |
1712 | may = MAY_READWRITE; | 1714 | may = MAY_READWRITE; |
1713 | break; | 1715 | break; |
1714 | case IPC_INFO: | 1716 | case IPC_INFO: |
1715 | case MSG_INFO: | 1717 | case MSG_INFO: |
1716 | /* | 1718 | /* |
1717 | * System level information | 1719 | * System level information |
1718 | */ | 1720 | */ |
1719 | return 0; | 1721 | return 0; |
1720 | default: | 1722 | default: |
1721 | return -EINVAL; | 1723 | return -EINVAL; |
1722 | } | 1724 | } |
1723 | 1725 | ||
1724 | return smk_curacc(msp, may); | 1726 | return smk_curacc(msp, may); |
1725 | } | 1727 | } |
1726 | 1728 | ||
1727 | /** | 1729 | /** |
1728 | * smack_msg_queue_msgsnd - Smack access check for msg_queue | 1730 | * smack_msg_queue_msgsnd - Smack access check for msg_queue |
1729 | * @msq: the object | 1731 | * @msq: the object |
1730 | * @msg: unused | 1732 | * @msg: unused |
1731 | * @msqflg: access requested | 1733 | * @msqflg: access requested |
1732 | * | 1734 | * |
1733 | * Returns 0 if current has the requested access, error code otherwise | 1735 | * Returns 0 if current has the requested access, error code otherwise |
1734 | */ | 1736 | */ |
1735 | static int smack_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, | 1737 | static int smack_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, |
1736 | int msqflg) | 1738 | int msqflg) |
1737 | { | 1739 | { |
1738 | char *msp = smack_of_msq(msq); | 1740 | char *msp = smack_of_msq(msq); |
1739 | int rc; | 1741 | int rc; |
1740 | 1742 | ||
1741 | rc = smack_flags_to_may(msqflg); | 1743 | rc = smack_flags_to_may(msqflg); |
1742 | return smk_curacc(msp, rc); | 1744 | return smk_curacc(msp, rc); |
1743 | } | 1745 | } |
1744 | 1746 | ||
1745 | /** | 1747 | /** |
1746 | * smack_msg_queue_msgsnd - Smack access check for msg_queue | 1748 | * smack_msg_queue_msgsnd - Smack access check for msg_queue |
1747 | * @msq: the object | 1749 | * @msq: the object |
1748 | * @msg: unused | 1750 | * @msg: unused |
1749 | * @target: unused | 1751 | * @target: unused |
1750 | * @type: unused | 1752 | * @type: unused |
1751 | * @mode: unused | 1753 | * @mode: unused |
1752 | * | 1754 | * |
1753 | * Returns 0 if current has read and write access, error code otherwise | 1755 | * Returns 0 if current has read and write access, error code otherwise |
1754 | */ | 1756 | */ |
1755 | static int smack_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, | 1757 | static int smack_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, |
1756 | struct task_struct *target, long type, int mode) | 1758 | struct task_struct *target, long type, int mode) |
1757 | { | 1759 | { |
1758 | char *msp = smack_of_msq(msq); | 1760 | char *msp = smack_of_msq(msq); |
1759 | 1761 | ||
1760 | return smk_curacc(msp, MAY_READWRITE); | 1762 | return smk_curacc(msp, MAY_READWRITE); |
1761 | } | 1763 | } |
1762 | 1764 | ||
1763 | /** | 1765 | /** |
1764 | * smack_ipc_permission - Smack access for ipc_permission() | 1766 | * smack_ipc_permission - Smack access for ipc_permission() |
1765 | * @ipp: the object permissions | 1767 | * @ipp: the object permissions |
1766 | * @flag: access requested | 1768 | * @flag: access requested |
1767 | * | 1769 | * |
1768 | * Returns 0 if current has read and write access, error code otherwise | 1770 | * Returns 0 if current has read and write access, error code otherwise |
1769 | */ | 1771 | */ |
1770 | static int smack_ipc_permission(struct kern_ipc_perm *ipp, short flag) | 1772 | static int smack_ipc_permission(struct kern_ipc_perm *ipp, short flag) |
1771 | { | 1773 | { |
1772 | char *isp = ipp->security; | 1774 | char *isp = ipp->security; |
1773 | int may; | 1775 | int may; |
1774 | 1776 | ||
1775 | may = smack_flags_to_may(flag); | 1777 | may = smack_flags_to_may(flag); |
1776 | return smk_curacc(isp, may); | 1778 | return smk_curacc(isp, may); |
1777 | } | 1779 | } |
1778 | 1780 | ||
1779 | /** | 1781 | /** |
1780 | * smack_d_instantiate - Make sure the blob is correct on an inode | 1782 | * smack_d_instantiate - Make sure the blob is correct on an inode |
1781 | * @opt_dentry: unused | 1783 | * @opt_dentry: unused |
1782 | * @inode: the object | 1784 | * @inode: the object |
1783 | * | 1785 | * |
1784 | * Set the inode's security blob if it hasn't been done already. | 1786 | * Set the inode's security blob if it hasn't been done already. |
1785 | */ | 1787 | */ |
1786 | static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | 1788 | static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) |
1787 | { | 1789 | { |
1788 | struct super_block *sbp; | 1790 | struct super_block *sbp; |
1789 | struct superblock_smack *sbsp; | 1791 | struct superblock_smack *sbsp; |
1790 | struct inode_smack *isp; | 1792 | struct inode_smack *isp; |
1791 | char *csp = current->security; | 1793 | char *csp = current->security; |
1792 | char *fetched; | 1794 | char *fetched; |
1793 | char *final; | 1795 | char *final; |
1794 | struct dentry *dp; | 1796 | struct dentry *dp; |
1795 | 1797 | ||
1796 | if (inode == NULL) | 1798 | if (inode == NULL) |
1797 | return; | 1799 | return; |
1798 | 1800 | ||
1799 | isp = inode->i_security; | 1801 | isp = inode->i_security; |
1800 | 1802 | ||
1801 | mutex_lock(&isp->smk_lock); | 1803 | mutex_lock(&isp->smk_lock); |
1802 | /* | 1804 | /* |
1803 | * If the inode is already instantiated | 1805 | * If the inode is already instantiated |
1804 | * take the quick way out | 1806 | * take the quick way out |
1805 | */ | 1807 | */ |
1806 | if (isp->smk_flags & SMK_INODE_INSTANT) | 1808 | if (isp->smk_flags & SMK_INODE_INSTANT) |
1807 | goto unlockandout; | 1809 | goto unlockandout; |
1808 | 1810 | ||
1809 | sbp = inode->i_sb; | 1811 | sbp = inode->i_sb; |
1810 | sbsp = sbp->s_security; | 1812 | sbsp = sbp->s_security; |
1811 | /* | 1813 | /* |
1812 | * We're going to use the superblock default label | 1814 | * We're going to use the superblock default label |
1813 | * if there's no label on the file. | 1815 | * if there's no label on the file. |
1814 | */ | 1816 | */ |
1815 | final = sbsp->smk_default; | 1817 | final = sbsp->smk_default; |
1816 | 1818 | ||
1817 | /* | 1819 | /* |
1818 | * This is pretty hackish. | 1820 | * This is pretty hackish. |
1819 | * Casey says that we shouldn't have to do | 1821 | * Casey says that we shouldn't have to do |
1820 | * file system specific code, but it does help | 1822 | * file system specific code, but it does help |
1821 | * with keeping it simple. | 1823 | * with keeping it simple. |
1822 | */ | 1824 | */ |
1823 | switch (sbp->s_magic) { | 1825 | switch (sbp->s_magic) { |
1824 | case SMACK_MAGIC: | 1826 | case SMACK_MAGIC: |
1825 | /* | 1827 | /* |
1826 | * Casey says that it's a little embarassing | 1828 | * Casey says that it's a little embarassing |
1827 | * that the smack file system doesn't do | 1829 | * that the smack file system doesn't do |
1828 | * extended attributes. | 1830 | * extended attributes. |
1829 | */ | 1831 | */ |
1830 | final = smack_known_star.smk_known; | 1832 | final = smack_known_star.smk_known; |
1831 | break; | 1833 | break; |
1832 | case PIPEFS_MAGIC: | 1834 | case PIPEFS_MAGIC: |
1833 | /* | 1835 | /* |
1834 | * Casey says pipes are easy (?) | 1836 | * Casey says pipes are easy (?) |
1835 | */ | 1837 | */ |
1836 | final = smack_known_star.smk_known; | 1838 | final = smack_known_star.smk_known; |
1837 | break; | 1839 | break; |
1838 | case DEVPTS_SUPER_MAGIC: | 1840 | case DEVPTS_SUPER_MAGIC: |
1839 | /* | 1841 | /* |
1840 | * devpts seems content with the label of the task. | 1842 | * devpts seems content with the label of the task. |
1841 | * Programs that change smack have to treat the | 1843 | * Programs that change smack have to treat the |
1842 | * pty with respect. | 1844 | * pty with respect. |
1843 | */ | 1845 | */ |
1844 | final = csp; | 1846 | final = csp; |
1845 | break; | 1847 | break; |
1846 | case SOCKFS_MAGIC: | 1848 | case SOCKFS_MAGIC: |
1847 | /* | 1849 | /* |
1848 | * Casey says sockets get the smack of the task. | 1850 | * Casey says sockets get the smack of the task. |
1849 | */ | 1851 | */ |
1850 | final = csp; | 1852 | final = csp; |
1851 | break; | 1853 | break; |
1852 | case PROC_SUPER_MAGIC: | 1854 | case PROC_SUPER_MAGIC: |
1853 | /* | 1855 | /* |
1854 | * Casey says procfs appears not to care. | 1856 | * Casey says procfs appears not to care. |
1855 | * The superblock default suffices. | 1857 | * The superblock default suffices. |
1856 | */ | 1858 | */ |
1857 | break; | 1859 | break; |
1858 | case TMPFS_MAGIC: | 1860 | case TMPFS_MAGIC: |
1859 | /* | 1861 | /* |
1860 | * Device labels should come from the filesystem, | 1862 | * Device labels should come from the filesystem, |
1861 | * but watch out, because they're volitile, | 1863 | * but watch out, because they're volitile, |
1862 | * getting recreated on every reboot. | 1864 | * getting recreated on every reboot. |
1863 | */ | 1865 | */ |
1864 | final = smack_known_star.smk_known; | 1866 | final = smack_known_star.smk_known; |
1865 | /* | 1867 | /* |
1866 | * No break. | 1868 | * No break. |
1867 | * | 1869 | * |
1868 | * If a smack value has been set we want to use it, | 1870 | * If a smack value has been set we want to use it, |
1869 | * but since tmpfs isn't giving us the opportunity | 1871 | * but since tmpfs isn't giving us the opportunity |
1870 | * to set mount options simulate setting the | 1872 | * to set mount options simulate setting the |
1871 | * superblock default. | 1873 | * superblock default. |
1872 | */ | 1874 | */ |
1873 | default: | 1875 | default: |
1874 | /* | 1876 | /* |
1875 | * This isn't an understood special case. | 1877 | * This isn't an understood special case. |
1876 | * Get the value from the xattr. | 1878 | * Get the value from the xattr. |
1877 | * | 1879 | * |
1878 | * No xattr support means, alas, no SMACK label. | 1880 | * No xattr support means, alas, no SMACK label. |
1879 | * Use the aforeapplied default. | 1881 | * Use the aforeapplied default. |
1880 | * It would be curious if the label of the task | 1882 | * It would be curious if the label of the task |
1881 | * does not match that assigned. | 1883 | * does not match that assigned. |
1882 | */ | 1884 | */ |
1883 | if (inode->i_op->getxattr == NULL) | 1885 | if (inode->i_op->getxattr == NULL) |
1884 | break; | 1886 | break; |
1885 | /* | 1887 | /* |
1886 | * Get the dentry for xattr. | 1888 | * Get the dentry for xattr. |
1887 | */ | 1889 | */ |
1888 | if (opt_dentry == NULL) { | 1890 | if (opt_dentry == NULL) { |
1889 | dp = d_find_alias(inode); | 1891 | dp = d_find_alias(inode); |
1890 | if (dp == NULL) | 1892 | if (dp == NULL) |
1891 | break; | 1893 | break; |
1892 | } else { | 1894 | } else { |
1893 | dp = dget(opt_dentry); | 1895 | dp = dget(opt_dentry); |
1894 | if (dp == NULL) | 1896 | if (dp == NULL) |
1895 | break; | 1897 | break; |
1896 | } | 1898 | } |
1897 | 1899 | ||
1898 | fetched = smk_fetch(inode, dp); | 1900 | fetched = smk_fetch(inode, dp); |
1899 | if (fetched != NULL) | 1901 | if (fetched != NULL) |
1900 | final = fetched; | 1902 | final = fetched; |
1901 | 1903 | ||
1902 | dput(dp); | 1904 | dput(dp); |
1903 | break; | 1905 | break; |
1904 | } | 1906 | } |
1905 | 1907 | ||
1906 | if (final == NULL) | 1908 | if (final == NULL) |
1907 | isp->smk_inode = csp; | 1909 | isp->smk_inode = csp; |
1908 | else | 1910 | else |
1909 | isp->smk_inode = final; | 1911 | isp->smk_inode = final; |
1910 | 1912 | ||
1911 | isp->smk_flags |= SMK_INODE_INSTANT; | 1913 | isp->smk_flags |= SMK_INODE_INSTANT; |
1912 | 1914 | ||
1913 | unlockandout: | 1915 | unlockandout: |
1914 | mutex_unlock(&isp->smk_lock); | 1916 | mutex_unlock(&isp->smk_lock); |
1915 | return; | 1917 | return; |
1916 | } | 1918 | } |
1917 | 1919 | ||
1918 | /** | 1920 | /** |
1919 | * smack_getprocattr - Smack process attribute access | 1921 | * smack_getprocattr - Smack process attribute access |
1920 | * @p: the object task | 1922 | * @p: the object task |
1921 | * @name: the name of the attribute in /proc/.../attr | 1923 | * @name: the name of the attribute in /proc/.../attr |
1922 | * @value: where to put the result | 1924 | * @value: where to put the result |
1923 | * | 1925 | * |
1924 | * Places a copy of the task Smack into value | 1926 | * Places a copy of the task Smack into value |
1925 | * | 1927 | * |
1926 | * Returns the length of the smack label or an error code | 1928 | * Returns the length of the smack label or an error code |
1927 | */ | 1929 | */ |
1928 | static int smack_getprocattr(struct task_struct *p, char *name, char **value) | 1930 | static int smack_getprocattr(struct task_struct *p, char *name, char **value) |
1929 | { | 1931 | { |
1930 | char *cp; | 1932 | char *cp; |
1931 | int slen; | 1933 | int slen; |
1932 | 1934 | ||
1933 | if (strcmp(name, "current") != 0) | 1935 | if (strcmp(name, "current") != 0) |
1934 | return -EINVAL; | 1936 | return -EINVAL; |
1935 | 1937 | ||
1936 | cp = kstrdup(p->security, GFP_KERNEL); | 1938 | cp = kstrdup(p->security, GFP_KERNEL); |
1937 | if (cp == NULL) | 1939 | if (cp == NULL) |
1938 | return -ENOMEM; | 1940 | return -ENOMEM; |
1939 | 1941 | ||
1940 | slen = strlen(cp); | 1942 | slen = strlen(cp); |
1941 | *value = cp; | 1943 | *value = cp; |
1942 | return slen; | 1944 | return slen; |
1943 | } | 1945 | } |
1944 | 1946 | ||
1945 | /** | 1947 | /** |
1946 | * smack_setprocattr - Smack process attribute setting | 1948 | * smack_setprocattr - Smack process attribute setting |
1947 | * @p: the object task | 1949 | * @p: the object task |
1948 | * @name: the name of the attribute in /proc/.../attr | 1950 | * @name: the name of the attribute in /proc/.../attr |
1949 | * @value: the value to set | 1951 | * @value: the value to set |
1950 | * @size: the size of the value | 1952 | * @size: the size of the value |
1951 | * | 1953 | * |
1952 | * Sets the Smack value of the task. Only setting self | 1954 | * Sets the Smack value of the task. Only setting self |
1953 | * is permitted and only with privilege | 1955 | * is permitted and only with privilege |
1954 | * | 1956 | * |
1955 | * Returns the length of the smack label or an error code | 1957 | * Returns the length of the smack label or an error code |
1956 | */ | 1958 | */ |
1957 | static int smack_setprocattr(struct task_struct *p, char *name, | 1959 | static int smack_setprocattr(struct task_struct *p, char *name, |
1958 | void *value, size_t size) | 1960 | void *value, size_t size) |
1959 | { | 1961 | { |
1960 | char *newsmack; | 1962 | char *newsmack; |
1961 | 1963 | ||
1962 | if (!__capable(p, CAP_MAC_ADMIN)) | 1964 | if (!__capable(p, CAP_MAC_ADMIN)) |
1963 | return -EPERM; | 1965 | return -EPERM; |
1964 | 1966 | ||
1965 | /* | 1967 | /* |
1966 | * Changing another process' Smack value is too dangerous | 1968 | * Changing another process' Smack value is too dangerous |
1967 | * and supports no sane use case. | 1969 | * and supports no sane use case. |
1968 | */ | 1970 | */ |
1969 | if (p != current) | 1971 | if (p != current) |
1970 | return -EPERM; | 1972 | return -EPERM; |
1971 | 1973 | ||
1972 | if (value == NULL || size == 0 || size >= SMK_LABELLEN) | 1974 | if (value == NULL || size == 0 || size >= SMK_LABELLEN) |
1973 | return -EINVAL; | 1975 | return -EINVAL; |
1974 | 1976 | ||
1975 | if (strcmp(name, "current") != 0) | 1977 | if (strcmp(name, "current") != 0) |
1976 | return -EINVAL; | 1978 | return -EINVAL; |
1977 | 1979 | ||
1978 | newsmack = smk_import(value, size); | 1980 | newsmack = smk_import(value, size); |
1979 | if (newsmack == NULL) | 1981 | if (newsmack == NULL) |
1980 | return -EINVAL; | 1982 | return -EINVAL; |
1981 | 1983 | ||
1982 | p->security = newsmack; | 1984 | p->security = newsmack; |
1983 | return size; | 1985 | return size; |
1984 | } | 1986 | } |
1985 | 1987 | ||
1986 | /** | 1988 | /** |
1987 | * smack_unix_stream_connect - Smack access on UDS | 1989 | * smack_unix_stream_connect - Smack access on UDS |
1988 | * @sock: one socket | 1990 | * @sock: one socket |
1989 | * @other: the other socket | 1991 | * @other: the other socket |
1990 | * @newsk: unused | 1992 | * @newsk: unused |
1991 | * | 1993 | * |
1992 | * Return 0 if a subject with the smack of sock could access | 1994 | * Return 0 if a subject with the smack of sock could access |
1993 | * an object with the smack of other, otherwise an error code | 1995 | * an object with the smack of other, otherwise an error code |
1994 | */ | 1996 | */ |
1995 | static int smack_unix_stream_connect(struct socket *sock, | 1997 | static int smack_unix_stream_connect(struct socket *sock, |
1996 | struct socket *other, struct sock *newsk) | 1998 | struct socket *other, struct sock *newsk) |
1997 | { | 1999 | { |
1998 | struct inode *sp = SOCK_INODE(sock); | 2000 | struct inode *sp = SOCK_INODE(sock); |
1999 | struct inode *op = SOCK_INODE(other); | 2001 | struct inode *op = SOCK_INODE(other); |
2000 | 2002 | ||
2001 | return smk_access(smk_of_inode(sp), smk_of_inode(op), MAY_READWRITE); | 2003 | return smk_access(smk_of_inode(sp), smk_of_inode(op), MAY_READWRITE); |
2002 | } | 2004 | } |
2003 | 2005 | ||
2004 | /** | 2006 | /** |
2005 | * smack_unix_may_send - Smack access on UDS | 2007 | * smack_unix_may_send - Smack access on UDS |
2006 | * @sock: one socket | 2008 | * @sock: one socket |
2007 | * @other: the other socket | 2009 | * @other: the other socket |
2008 | * | 2010 | * |
2009 | * Return 0 if a subject with the smack of sock could access | 2011 | * Return 0 if a subject with the smack of sock could access |
2010 | * an object with the smack of other, otherwise an error code | 2012 | * an object with the smack of other, otherwise an error code |
2011 | */ | 2013 | */ |
2012 | static int smack_unix_may_send(struct socket *sock, struct socket *other) | 2014 | static int smack_unix_may_send(struct socket *sock, struct socket *other) |
2013 | { | 2015 | { |
2014 | struct inode *sp = SOCK_INODE(sock); | 2016 | struct inode *sp = SOCK_INODE(sock); |
2015 | struct inode *op = SOCK_INODE(other); | 2017 | struct inode *op = SOCK_INODE(other); |
2016 | 2018 | ||
2017 | return smk_access(smk_of_inode(sp), smk_of_inode(op), MAY_WRITE); | 2019 | return smk_access(smk_of_inode(sp), smk_of_inode(op), MAY_WRITE); |
2018 | } | 2020 | } |
2019 | 2021 | ||
2020 | /** | 2022 | /** |
2021 | * smack_from_secattr - Convert a netlabel attr.mls.lvl/attr.mls.cat | 2023 | * smack_from_secattr - Convert a netlabel attr.mls.lvl/attr.mls.cat |
2022 | * pair to smack | 2024 | * pair to smack |
2023 | * @sap: netlabel secattr | 2025 | * @sap: netlabel secattr |
2024 | * @sip: where to put the result | 2026 | * @sip: where to put the result |
2025 | * | 2027 | * |
2026 | * Copies a smack label into sip | 2028 | * Copies a smack label into sip |
2027 | */ | 2029 | */ |
2028 | static void smack_from_secattr(struct netlbl_lsm_secattr *sap, char *sip) | 2030 | static void smack_from_secattr(struct netlbl_lsm_secattr *sap, char *sip) |
2029 | { | 2031 | { |
2030 | char smack[SMK_LABELLEN]; | 2032 | char smack[SMK_LABELLEN]; |
2031 | int pcat; | 2033 | int pcat; |
2032 | 2034 | ||
2033 | if ((sap->flags & NETLBL_SECATTR_MLS_LVL) == 0) { | 2035 | if ((sap->flags & NETLBL_SECATTR_MLS_LVL) == 0) { |
2034 | /* | 2036 | /* |
2035 | * If there are flags but no level netlabel isn't | 2037 | * If there are flags but no level netlabel isn't |
2036 | * behaving the way we expect it to. | 2038 | * behaving the way we expect it to. |
2037 | * | 2039 | * |
2038 | * Without guidance regarding the smack value | 2040 | * Without guidance regarding the smack value |
2039 | * for the packet fall back on the network | 2041 | * for the packet fall back on the network |
2040 | * ambient value. | 2042 | * ambient value. |
2041 | */ | 2043 | */ |
2042 | strncpy(sip, smack_net_ambient, SMK_MAXLEN); | 2044 | strncpy(sip, smack_net_ambient, SMK_MAXLEN); |
2043 | return; | 2045 | return; |
2044 | } | 2046 | } |
2045 | /* | 2047 | /* |
2046 | * Get the categories, if any | 2048 | * Get the categories, if any |
2047 | */ | 2049 | */ |
2048 | memset(smack, '\0', SMK_LABELLEN); | 2050 | memset(smack, '\0', SMK_LABELLEN); |
2049 | if ((sap->flags & NETLBL_SECATTR_MLS_CAT) != 0) | 2051 | if ((sap->flags & NETLBL_SECATTR_MLS_CAT) != 0) |
2050 | for (pcat = -1;;) { | 2052 | for (pcat = -1;;) { |
2051 | pcat = netlbl_secattr_catmap_walk(sap->attr.mls.cat, | 2053 | pcat = netlbl_secattr_catmap_walk(sap->attr.mls.cat, |
2052 | pcat + 1); | 2054 | pcat + 1); |
2053 | if (pcat < 0) | 2055 | if (pcat < 0) |
2054 | break; | 2056 | break; |
2055 | smack_catset_bit(pcat, smack); | 2057 | smack_catset_bit(pcat, smack); |
2056 | } | 2058 | } |
2057 | /* | 2059 | /* |
2058 | * If it is CIPSO using smack direct mapping | 2060 | * If it is CIPSO using smack direct mapping |
2059 | * we are already done. WeeHee. | 2061 | * we are already done. WeeHee. |
2060 | */ | 2062 | */ |
2061 | if (sap->attr.mls.lvl == smack_cipso_direct) { | 2063 | if (sap->attr.mls.lvl == smack_cipso_direct) { |
2062 | memcpy(sip, smack, SMK_MAXLEN); | 2064 | memcpy(sip, smack, SMK_MAXLEN); |
2063 | return; | 2065 | return; |
2064 | } | 2066 | } |
2065 | /* | 2067 | /* |
2066 | * Look it up in the supplied table if it is not a direct mapping. | 2068 | * Look it up in the supplied table if it is not a direct mapping. |
2067 | */ | 2069 | */ |
2068 | smack_from_cipso(sap->attr.mls.lvl, smack, sip); | 2070 | smack_from_cipso(sap->attr.mls.lvl, smack, sip); |
2069 | return; | 2071 | return; |
2070 | } | 2072 | } |
2071 | 2073 | ||
2072 | /** | 2074 | /** |
2073 | * smack_socket_sock_rcv_skb - Smack packet delivery access check | 2075 | * smack_socket_sock_rcv_skb - Smack packet delivery access check |
2074 | * @sk: socket | 2076 | * @sk: socket |
2075 | * @skb: packet | 2077 | * @skb: packet |
2076 | * | 2078 | * |
2077 | * Returns 0 if the packet should be delivered, an error code otherwise | 2079 | * Returns 0 if the packet should be delivered, an error code otherwise |
2078 | */ | 2080 | */ |
2079 | static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | 2081 | static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) |
2080 | { | 2082 | { |
2081 | struct netlbl_lsm_secattr secattr; | 2083 | struct netlbl_lsm_secattr secattr; |
2082 | struct socket_smack *ssp = sk->sk_security; | 2084 | struct socket_smack *ssp = sk->sk_security; |
2083 | char smack[SMK_LABELLEN]; | 2085 | char smack[SMK_LABELLEN]; |
2084 | int rc; | 2086 | int rc; |
2085 | 2087 | ||
2086 | if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6) | 2088 | if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6) |
2087 | return 0; | 2089 | return 0; |
2088 | 2090 | ||
2089 | /* | 2091 | /* |
2090 | * Translate what netlabel gave us. | 2092 | * Translate what netlabel gave us. |
2091 | */ | 2093 | */ |
2092 | memset(smack, '\0', SMK_LABELLEN); | 2094 | memset(smack, '\0', SMK_LABELLEN); |
2093 | netlbl_secattr_init(&secattr); | 2095 | netlbl_secattr_init(&secattr); |
2094 | rc = netlbl_skbuff_getattr(skb, sk->sk_family, &secattr); | 2096 | rc = netlbl_skbuff_getattr(skb, sk->sk_family, &secattr); |
2095 | if (rc == 0) | 2097 | if (rc == 0) |
2096 | smack_from_secattr(&secattr, smack); | 2098 | smack_from_secattr(&secattr, smack); |
2097 | else | 2099 | else |
2098 | strncpy(smack, smack_net_ambient, SMK_MAXLEN); | 2100 | strncpy(smack, smack_net_ambient, SMK_MAXLEN); |
2099 | netlbl_secattr_destroy(&secattr); | 2101 | netlbl_secattr_destroy(&secattr); |
2100 | /* | 2102 | /* |
2101 | * Receiving a packet requires that the other end | 2103 | * Receiving a packet requires that the other end |
2102 | * be able to write here. Read access is not required. | 2104 | * be able to write here. Read access is not required. |
2103 | * This is the simplist possible security model | 2105 | * This is the simplist possible security model |
2104 | * for networking. | 2106 | * for networking. |
2105 | */ | 2107 | */ |
2106 | return smk_access(smack, ssp->smk_in, MAY_WRITE); | 2108 | return smk_access(smack, ssp->smk_in, MAY_WRITE); |
2107 | } | 2109 | } |
2108 | 2110 | ||
2109 | /** | 2111 | /** |
2110 | * smack_socket_getpeersec_stream - pull in packet label | 2112 | * smack_socket_getpeersec_stream - pull in packet label |
2111 | * @sock: the socket | 2113 | * @sock: the socket |
2112 | * @optval: user's destination | 2114 | * @optval: user's destination |
2113 | * @optlen: size thereof | 2115 | * @optlen: size thereof |
2114 | * @len: max thereoe | 2116 | * @len: max thereoe |
2115 | * | 2117 | * |
2116 | * returns zero on success, an error code otherwise | 2118 | * returns zero on success, an error code otherwise |
2117 | */ | 2119 | */ |
2118 | static int smack_socket_getpeersec_stream(struct socket *sock, | 2120 | static int smack_socket_getpeersec_stream(struct socket *sock, |
2119 | char __user *optval, | 2121 | char __user *optval, |
2120 | int __user *optlen, unsigned len) | 2122 | int __user *optlen, unsigned len) |
2121 | { | 2123 | { |
2122 | struct socket_smack *ssp; | 2124 | struct socket_smack *ssp; |
2123 | int slen; | 2125 | int slen; |
2124 | int rc = 0; | 2126 | int rc = 0; |
2125 | 2127 | ||
2126 | ssp = sock->sk->sk_security; | 2128 | ssp = sock->sk->sk_security; |
2127 | slen = strlen(ssp->smk_packet) + 1; | 2129 | slen = strlen(ssp->smk_packet) + 1; |
2128 | 2130 | ||
2129 | if (slen > len) | 2131 | if (slen > len) |
2130 | rc = -ERANGE; | 2132 | rc = -ERANGE; |
2131 | else if (copy_to_user(optval, ssp->smk_packet, slen) != 0) | 2133 | else if (copy_to_user(optval, ssp->smk_packet, slen) != 0) |
2132 | rc = -EFAULT; | 2134 | rc = -EFAULT; |
2133 | 2135 | ||
2134 | if (put_user(slen, optlen) != 0) | 2136 | if (put_user(slen, optlen) != 0) |
2135 | rc = -EFAULT; | 2137 | rc = -EFAULT; |
2136 | 2138 | ||
2137 | return rc; | 2139 | return rc; |
2138 | } | 2140 | } |
2139 | 2141 | ||
2140 | 2142 | ||
2141 | /** | 2143 | /** |
2142 | * smack_socket_getpeersec_dgram - pull in packet label | 2144 | * smack_socket_getpeersec_dgram - pull in packet label |
2143 | * @sock: the socket | 2145 | * @sock: the socket |
2144 | * @skb: packet data | 2146 | * @skb: packet data |
2145 | * @secid: pointer to where to put the secid of the packet | 2147 | * @secid: pointer to where to put the secid of the packet |
2146 | * | 2148 | * |
2147 | * Sets the netlabel socket state on sk from parent | 2149 | * Sets the netlabel socket state on sk from parent |
2148 | */ | 2150 | */ |
2149 | static int smack_socket_getpeersec_dgram(struct socket *sock, | 2151 | static int smack_socket_getpeersec_dgram(struct socket *sock, |
2150 | struct sk_buff *skb, u32 *secid) | 2152 | struct sk_buff *skb, u32 *secid) |
2151 | 2153 | ||
2152 | { | 2154 | { |
2153 | struct netlbl_lsm_secattr secattr; | 2155 | struct netlbl_lsm_secattr secattr; |
2154 | struct sock *sk; | 2156 | struct sock *sk; |
2155 | char smack[SMK_LABELLEN]; | 2157 | char smack[SMK_LABELLEN]; |
2156 | int family = PF_INET; | 2158 | int family = PF_INET; |
2157 | u32 s; | 2159 | u32 s; |
2158 | int rc; | 2160 | int rc; |
2159 | 2161 | ||
2160 | /* | 2162 | /* |
2161 | * Only works for families with packets. | 2163 | * Only works for families with packets. |
2162 | */ | 2164 | */ |
2163 | if (sock != NULL) { | 2165 | if (sock != NULL) { |
2164 | sk = sock->sk; | 2166 | sk = sock->sk; |
2165 | if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6) | 2167 | if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6) |
2166 | return 0; | 2168 | return 0; |
2167 | family = sk->sk_family; | 2169 | family = sk->sk_family; |
2168 | } | 2170 | } |
2169 | /* | 2171 | /* |
2170 | * Translate what netlabel gave us. | 2172 | * Translate what netlabel gave us. |
2171 | */ | 2173 | */ |
2172 | memset(smack, '\0', SMK_LABELLEN); | 2174 | memset(smack, '\0', SMK_LABELLEN); |
2173 | netlbl_secattr_init(&secattr); | 2175 | netlbl_secattr_init(&secattr); |
2174 | rc = netlbl_skbuff_getattr(skb, family, &secattr); | 2176 | rc = netlbl_skbuff_getattr(skb, family, &secattr); |
2175 | if (rc == 0) | 2177 | if (rc == 0) |
2176 | smack_from_secattr(&secattr, smack); | 2178 | smack_from_secattr(&secattr, smack); |
2177 | netlbl_secattr_destroy(&secattr); | 2179 | netlbl_secattr_destroy(&secattr); |
2178 | 2180 | ||
2179 | /* | 2181 | /* |
2180 | * Give up if we couldn't get anything | 2182 | * Give up if we couldn't get anything |
2181 | */ | 2183 | */ |
2182 | if (rc != 0) | 2184 | if (rc != 0) |
2183 | return rc; | 2185 | return rc; |
2184 | 2186 | ||
2185 | s = smack_to_secid(smack); | 2187 | s = smack_to_secid(smack); |
2186 | if (s == 0) | 2188 | if (s == 0) |
2187 | return -EINVAL; | 2189 | return -EINVAL; |
2188 | 2190 | ||
2189 | *secid = s; | 2191 | *secid = s; |
2190 | return 0; | 2192 | return 0; |
2191 | } | 2193 | } |
2192 | 2194 | ||
2193 | /** | 2195 | /** |
2194 | * smack_sock_graft - graft access state between two sockets | 2196 | * smack_sock_graft - graft access state between two sockets |
2195 | * @sk: fresh sock | 2197 | * @sk: fresh sock |
2196 | * @parent: donor socket | 2198 | * @parent: donor socket |
2197 | * | 2199 | * |
2198 | * Sets the netlabel socket state on sk from parent | 2200 | * Sets the netlabel socket state on sk from parent |
2199 | */ | 2201 | */ |
2200 | static void smack_sock_graft(struct sock *sk, struct socket *parent) | 2202 | static void smack_sock_graft(struct sock *sk, struct socket *parent) |
2201 | { | 2203 | { |
2202 | struct socket_smack *ssp; | 2204 | struct socket_smack *ssp; |
2203 | int rc; | 2205 | int rc; |
2204 | 2206 | ||
2205 | if (sk == NULL) | 2207 | if (sk == NULL) |
2206 | return; | 2208 | return; |
2207 | 2209 | ||
2208 | if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6) | 2210 | if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6) |
2209 | return; | 2211 | return; |
2210 | 2212 | ||
2211 | ssp = sk->sk_security; | 2213 | ssp = sk->sk_security; |
2212 | ssp->smk_in = current->security; | 2214 | ssp->smk_in = current->security; |
2213 | ssp->smk_out = current->security; | 2215 | ssp->smk_out = current->security; |
2214 | ssp->smk_packet[0] = '\0'; | 2216 | ssp->smk_packet[0] = '\0'; |
2215 | 2217 | ||
2216 | rc = smack_netlabel(sk); | 2218 | rc = smack_netlabel(sk); |
2219 | if (rc != 0) | ||
2220 | printk(KERN_WARNING "Smack: \"%s\" netlbl error %d.\n", | ||
2221 | __func__, -rc); | ||
2217 | } | 2222 | } |
2218 | 2223 | ||
2219 | /** | 2224 | /** |
2220 | * smack_inet_conn_request - Smack access check on connect | 2225 | * smack_inet_conn_request - Smack access check on connect |
2221 | * @sk: socket involved | 2226 | * @sk: socket involved |
2222 | * @skb: packet | 2227 | * @skb: packet |
2223 | * @req: unused | 2228 | * @req: unused |
2224 | * | 2229 | * |
2225 | * Returns 0 if a task with the packet label could write to | 2230 | * Returns 0 if a task with the packet label could write to |
2226 | * the socket, otherwise an error code | 2231 | * the socket, otherwise an error code |
2227 | */ | 2232 | */ |
2228 | static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, | 2233 | static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, |
2229 | struct request_sock *req) | 2234 | struct request_sock *req) |
2230 | { | 2235 | { |
2231 | struct netlbl_lsm_secattr skb_secattr; | 2236 | struct netlbl_lsm_secattr skb_secattr; |
2232 | struct socket_smack *ssp = sk->sk_security; | 2237 | struct socket_smack *ssp = sk->sk_security; |
2233 | char smack[SMK_LABELLEN]; | 2238 | char smack[SMK_LABELLEN]; |
2234 | int rc; | 2239 | int rc; |
2235 | 2240 | ||
2236 | if (skb == NULL) | 2241 | if (skb == NULL) |
2237 | return -EACCES; | 2242 | return -EACCES; |
2238 | 2243 | ||
2239 | memset(smack, '\0', SMK_LABELLEN); | 2244 | memset(smack, '\0', SMK_LABELLEN); |
2240 | netlbl_secattr_init(&skb_secattr); | 2245 | netlbl_secattr_init(&skb_secattr); |
2241 | rc = netlbl_skbuff_getattr(skb, sk->sk_family, &skb_secattr); | 2246 | rc = netlbl_skbuff_getattr(skb, sk->sk_family, &skb_secattr); |
2242 | if (rc == 0) | 2247 | if (rc == 0) |
2243 | smack_from_secattr(&skb_secattr, smack); | 2248 | smack_from_secattr(&skb_secattr, smack); |
2244 | else | 2249 | else |
2245 | strncpy(smack, smack_known_huh.smk_known, SMK_MAXLEN); | 2250 | strncpy(smack, smack_known_huh.smk_known, SMK_MAXLEN); |
2246 | netlbl_secattr_destroy(&skb_secattr); | 2251 | netlbl_secattr_destroy(&skb_secattr); |
2247 | /* | 2252 | /* |
2248 | * Receiving a packet requires that the other end | 2253 | * Receiving a packet requires that the other end |
2249 | * be able to write here. Read access is not required. | 2254 | * be able to write here. Read access is not required. |
2250 | * | 2255 | * |
2251 | * If the request is successful save the peer's label | 2256 | * If the request is successful save the peer's label |
2252 | * so that SO_PEERCRED can report it. | 2257 | * so that SO_PEERCRED can report it. |
2253 | */ | 2258 | */ |
2254 | rc = smk_access(smack, ssp->smk_in, MAY_WRITE); | 2259 | rc = smk_access(smack, ssp->smk_in, MAY_WRITE); |
2255 | if (rc == 0) | 2260 | if (rc == 0) |
2256 | strncpy(ssp->smk_packet, smack, SMK_MAXLEN); | 2261 | strncpy(ssp->smk_packet, smack, SMK_MAXLEN); |
2257 | 2262 | ||
2258 | return rc; | 2263 | return rc; |
2259 | } | 2264 | } |
2260 | 2265 | ||
2261 | /* | 2266 | /* |
2262 | * Key management security hooks | 2267 | * Key management security hooks |
2263 | * | 2268 | * |
2264 | * Casey has not tested key support very heavily. | 2269 | * Casey has not tested key support very heavily. |
2265 | * The permission check is most likely too restrictive. | 2270 | * The permission check is most likely too restrictive. |
2266 | * If you care about keys please have a look. | 2271 | * If you care about keys please have a look. |
2267 | */ | 2272 | */ |
2268 | #ifdef CONFIG_KEYS | 2273 | #ifdef CONFIG_KEYS |
2269 | 2274 | ||
2270 | /** | 2275 | /** |
2271 | * smack_key_alloc - Set the key security blob | 2276 | * smack_key_alloc - Set the key security blob |
2272 | * @key: object | 2277 | * @key: object |
2273 | * @tsk: the task associated with the key | 2278 | * @tsk: the task associated with the key |
2274 | * @flags: unused | 2279 | * @flags: unused |
2275 | * | 2280 | * |
2276 | * No allocation required | 2281 | * No allocation required |
2277 | * | 2282 | * |
2278 | * Returns 0 | 2283 | * Returns 0 |
2279 | */ | 2284 | */ |
2280 | static int smack_key_alloc(struct key *key, struct task_struct *tsk, | 2285 | static int smack_key_alloc(struct key *key, struct task_struct *tsk, |
2281 | unsigned long flags) | 2286 | unsigned long flags) |
2282 | { | 2287 | { |
2283 | key->security = tsk->security; | 2288 | key->security = tsk->security; |
2284 | return 0; | 2289 | return 0; |
2285 | } | 2290 | } |
2286 | 2291 | ||
2287 | /** | 2292 | /** |
2288 | * smack_key_free - Clear the key security blob | 2293 | * smack_key_free - Clear the key security blob |
2289 | * @key: the object | 2294 | * @key: the object |
2290 | * | 2295 | * |
2291 | * Clear the blob pointer | 2296 | * Clear the blob pointer |
2292 | */ | 2297 | */ |
2293 | static void smack_key_free(struct key *key) | 2298 | static void smack_key_free(struct key *key) |
2294 | { | 2299 | { |
2295 | key->security = NULL; | 2300 | key->security = NULL; |
2296 | } | 2301 | } |
2297 | 2302 | ||
2298 | /* | 2303 | /* |
2299 | * smack_key_permission - Smack access on a key | 2304 | * smack_key_permission - Smack access on a key |
2300 | * @key_ref: gets to the object | 2305 | * @key_ref: gets to the object |
2301 | * @context: task involved | 2306 | * @context: task involved |
2302 | * @perm: unused | 2307 | * @perm: unused |
2303 | * | 2308 | * |
2304 | * Return 0 if the task has read and write to the object, | 2309 | * Return 0 if the task has read and write to the object, |
2305 | * an error code otherwise | 2310 | * an error code otherwise |
2306 | */ | 2311 | */ |
2307 | static int smack_key_permission(key_ref_t key_ref, | 2312 | static int smack_key_permission(key_ref_t key_ref, |
2308 | struct task_struct *context, key_perm_t perm) | 2313 | struct task_struct *context, key_perm_t perm) |
2309 | { | 2314 | { |
2310 | struct key *keyp; | 2315 | struct key *keyp; |
2311 | 2316 | ||
2312 | keyp = key_ref_to_ptr(key_ref); | 2317 | keyp = key_ref_to_ptr(key_ref); |
2313 | if (keyp == NULL) | 2318 | if (keyp == NULL) |
2314 | return -EINVAL; | 2319 | return -EINVAL; |
2315 | /* | 2320 | /* |
2316 | * If the key hasn't been initialized give it access so that | 2321 | * If the key hasn't been initialized give it access so that |
2317 | * it may do so. | 2322 | * it may do so. |
2318 | */ | 2323 | */ |
2319 | if (keyp->security == NULL) | 2324 | if (keyp->security == NULL) |
2320 | return 0; | 2325 | return 0; |
2321 | /* | 2326 | /* |
2322 | * This should not occur | 2327 | * This should not occur |
2323 | */ | 2328 | */ |
2324 | if (context->security == NULL) | 2329 | if (context->security == NULL) |
2325 | return -EACCES; | 2330 | return -EACCES; |
2326 | 2331 | ||
2327 | return smk_access(context->security, keyp->security, MAY_READWRITE); | 2332 | return smk_access(context->security, keyp->security, MAY_READWRITE); |
2328 | } | 2333 | } |
2329 | #endif /* CONFIG_KEYS */ | 2334 | #endif /* CONFIG_KEYS */ |
2330 | 2335 | ||
2331 | /* | 2336 | /* |
2332 | * smack_secid_to_secctx - return the smack label for a secid | 2337 | * smack_secid_to_secctx - return the smack label for a secid |
2333 | * @secid: incoming integer | 2338 | * @secid: incoming integer |
2334 | * @secdata: destination | 2339 | * @secdata: destination |
2335 | * @seclen: how long it is | 2340 | * @seclen: how long it is |
2336 | * | 2341 | * |
2337 | * Exists for networking code. | 2342 | * Exists for networking code. |
2338 | */ | 2343 | */ |
2339 | static int smack_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) | 2344 | static int smack_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) |
2340 | { | 2345 | { |
2341 | char *sp = smack_from_secid(secid); | 2346 | char *sp = smack_from_secid(secid); |
2342 | 2347 | ||
2343 | *secdata = sp; | 2348 | *secdata = sp; |
2344 | *seclen = strlen(sp); | 2349 | *seclen = strlen(sp); |
2345 | return 0; | 2350 | return 0; |
2346 | } | 2351 | } |
2347 | 2352 | ||
2348 | /* | 2353 | /* |
2354 | * smack_secctx_to_secid - return the secid for a smack label | ||
2355 | * @secdata: smack label | ||
2356 | * @seclen: how long result is | ||
2357 | * @secid: outgoing integer | ||
2358 | * | ||
2359 | * Exists for audit and networking code. | ||
2360 | */ | ||
2361 | static int smack_secctx_to_secid(char *secdata, u32 seclen, u32 *secid) | ||
2362 | { | ||
2363 | *secid = smack_to_secid(secdata); | ||
2364 | return 0; | ||
2365 | } | ||
2366 | |||
2367 | /* | ||
2349 | * smack_release_secctx - don't do anything. | 2368 | * smack_release_secctx - don't do anything. |
2350 | * @key_ref: unused | 2369 | * @key_ref: unused |
2351 | * @context: unused | 2370 | * @context: unused |
2352 | * @perm: unused | 2371 | * @perm: unused |
2353 | * | 2372 | * |
2354 | * Exists to make sure nothing gets done, and properly | 2373 | * Exists to make sure nothing gets done, and properly |
2355 | */ | 2374 | */ |
2356 | static void smack_release_secctx(char *secdata, u32 seclen) | 2375 | static void smack_release_secctx(char *secdata, u32 seclen) |
2357 | { | 2376 | { |
2358 | } | 2377 | } |
2359 | 2378 | ||
2360 | static struct security_operations smack_ops = { | 2379 | static struct security_operations smack_ops = { |
2361 | .ptrace = smack_ptrace, | 2380 | .ptrace = smack_ptrace, |
2362 | .capget = cap_capget, | 2381 | .capget = cap_capget, |
2363 | .capset_check = cap_capset_check, | 2382 | .capset_check = cap_capset_check, |
2364 | .capset_set = cap_capset_set, | 2383 | .capset_set = cap_capset_set, |
2365 | .capable = cap_capable, | 2384 | .capable = cap_capable, |
2366 | .syslog = smack_syslog, | 2385 | .syslog = smack_syslog, |
2367 | .settime = cap_settime, | 2386 | .settime = cap_settime, |
2368 | .vm_enough_memory = cap_vm_enough_memory, | 2387 | .vm_enough_memory = cap_vm_enough_memory, |
2369 | 2388 | ||
2370 | .bprm_apply_creds = cap_bprm_apply_creds, | 2389 | .bprm_apply_creds = cap_bprm_apply_creds, |
2371 | .bprm_set_security = cap_bprm_set_security, | 2390 | .bprm_set_security = cap_bprm_set_security, |
2372 | .bprm_secureexec = cap_bprm_secureexec, | 2391 | .bprm_secureexec = cap_bprm_secureexec, |
2373 | 2392 | ||
2374 | .sb_alloc_security = smack_sb_alloc_security, | 2393 | .sb_alloc_security = smack_sb_alloc_security, |
2375 | .sb_free_security = smack_sb_free_security, | 2394 | .sb_free_security = smack_sb_free_security, |
2376 | .sb_copy_data = smack_sb_copy_data, | 2395 | .sb_copy_data = smack_sb_copy_data, |
2377 | .sb_kern_mount = smack_sb_kern_mount, | 2396 | .sb_kern_mount = smack_sb_kern_mount, |
2378 | .sb_statfs = smack_sb_statfs, | 2397 | .sb_statfs = smack_sb_statfs, |
2379 | .sb_mount = smack_sb_mount, | 2398 | .sb_mount = smack_sb_mount, |
2380 | .sb_umount = smack_sb_umount, | 2399 | .sb_umount = smack_sb_umount, |
2381 | 2400 | ||
2382 | .inode_alloc_security = smack_inode_alloc_security, | 2401 | .inode_alloc_security = smack_inode_alloc_security, |
2383 | .inode_free_security = smack_inode_free_security, | 2402 | .inode_free_security = smack_inode_free_security, |
2384 | .inode_init_security = smack_inode_init_security, | 2403 | .inode_init_security = smack_inode_init_security, |
2385 | .inode_link = smack_inode_link, | 2404 | .inode_link = smack_inode_link, |
2386 | .inode_unlink = smack_inode_unlink, | 2405 | .inode_unlink = smack_inode_unlink, |
2387 | .inode_rmdir = smack_inode_rmdir, | 2406 | .inode_rmdir = smack_inode_rmdir, |
2388 | .inode_rename = smack_inode_rename, | 2407 | .inode_rename = smack_inode_rename, |
2389 | .inode_permission = smack_inode_permission, | 2408 | .inode_permission = smack_inode_permission, |
2390 | .inode_setattr = smack_inode_setattr, | 2409 | .inode_setattr = smack_inode_setattr, |
2391 | .inode_getattr = smack_inode_getattr, | 2410 | .inode_getattr = smack_inode_getattr, |
2392 | .inode_setxattr = smack_inode_setxattr, | 2411 | .inode_setxattr = smack_inode_setxattr, |
2393 | .inode_post_setxattr = smack_inode_post_setxattr, | 2412 | .inode_post_setxattr = smack_inode_post_setxattr, |
2394 | .inode_getxattr = smack_inode_getxattr, | 2413 | .inode_getxattr = smack_inode_getxattr, |
2395 | .inode_removexattr = smack_inode_removexattr, | 2414 | .inode_removexattr = smack_inode_removexattr, |
2396 | .inode_getsecurity = smack_inode_getsecurity, | 2415 | .inode_getsecurity = smack_inode_getsecurity, |
2397 | .inode_setsecurity = smack_inode_setsecurity, | 2416 | .inode_setsecurity = smack_inode_setsecurity, |
2398 | .inode_listsecurity = smack_inode_listsecurity, | 2417 | .inode_listsecurity = smack_inode_listsecurity, |
2399 | 2418 | ||
2400 | .file_permission = smack_file_permission, | 2419 | .file_permission = smack_file_permission, |
2401 | .file_alloc_security = smack_file_alloc_security, | 2420 | .file_alloc_security = smack_file_alloc_security, |
2402 | .file_free_security = smack_file_free_security, | 2421 | .file_free_security = smack_file_free_security, |
2403 | .file_ioctl = smack_file_ioctl, | 2422 | .file_ioctl = smack_file_ioctl, |
2404 | .file_lock = smack_file_lock, | 2423 | .file_lock = smack_file_lock, |
2405 | .file_fcntl = smack_file_fcntl, | 2424 | .file_fcntl = smack_file_fcntl, |
2406 | .file_set_fowner = smack_file_set_fowner, | 2425 | .file_set_fowner = smack_file_set_fowner, |
2407 | .file_send_sigiotask = smack_file_send_sigiotask, | 2426 | .file_send_sigiotask = smack_file_send_sigiotask, |
2408 | .file_receive = smack_file_receive, | 2427 | .file_receive = smack_file_receive, |
2409 | 2428 | ||
2410 | .task_alloc_security = smack_task_alloc_security, | 2429 | .task_alloc_security = smack_task_alloc_security, |
2411 | .task_free_security = smack_task_free_security, | 2430 | .task_free_security = smack_task_free_security, |
2412 | .task_post_setuid = cap_task_post_setuid, | 2431 | .task_post_setuid = cap_task_post_setuid, |
2413 | .task_setpgid = smack_task_setpgid, | 2432 | .task_setpgid = smack_task_setpgid, |
2414 | .task_getpgid = smack_task_getpgid, | 2433 | .task_getpgid = smack_task_getpgid, |
2415 | .task_getsid = smack_task_getsid, | 2434 | .task_getsid = smack_task_getsid, |
2416 | .task_getsecid = smack_task_getsecid, | 2435 | .task_getsecid = smack_task_getsecid, |
2417 | .task_setnice = smack_task_setnice, | 2436 | .task_setnice = smack_task_setnice, |
2418 | .task_setioprio = smack_task_setioprio, | 2437 | .task_setioprio = smack_task_setioprio, |
2419 | .task_getioprio = smack_task_getioprio, | 2438 | .task_getioprio = smack_task_getioprio, |
2420 | .task_setscheduler = smack_task_setscheduler, | 2439 | .task_setscheduler = smack_task_setscheduler, |
2421 | .task_getscheduler = smack_task_getscheduler, | 2440 | .task_getscheduler = smack_task_getscheduler, |
2422 | .task_movememory = smack_task_movememory, | 2441 | .task_movememory = smack_task_movememory, |
2423 | .task_kill = smack_task_kill, | 2442 | .task_kill = smack_task_kill, |
2424 | .task_wait = smack_task_wait, | 2443 | .task_wait = smack_task_wait, |
2425 | .task_reparent_to_init = cap_task_reparent_to_init, | 2444 | .task_reparent_to_init = cap_task_reparent_to_init, |
2426 | .task_to_inode = smack_task_to_inode, | 2445 | .task_to_inode = smack_task_to_inode, |
2427 | 2446 | ||
2428 | .ipc_permission = smack_ipc_permission, | 2447 | .ipc_permission = smack_ipc_permission, |
2429 | 2448 | ||
2430 | .msg_msg_alloc_security = smack_msg_msg_alloc_security, | 2449 | .msg_msg_alloc_security = smack_msg_msg_alloc_security, |
2431 | .msg_msg_free_security = smack_msg_msg_free_security, | 2450 | .msg_msg_free_security = smack_msg_msg_free_security, |
2432 | 2451 | ||
2433 | .msg_queue_alloc_security = smack_msg_queue_alloc_security, | 2452 | .msg_queue_alloc_security = smack_msg_queue_alloc_security, |
2434 | .msg_queue_free_security = smack_msg_queue_free_security, | 2453 | .msg_queue_free_security = smack_msg_queue_free_security, |
2435 | .msg_queue_associate = smack_msg_queue_associate, | 2454 | .msg_queue_associate = smack_msg_queue_associate, |
2436 | .msg_queue_msgctl = smack_msg_queue_msgctl, | 2455 | .msg_queue_msgctl = smack_msg_queue_msgctl, |
2437 | .msg_queue_msgsnd = smack_msg_queue_msgsnd, | 2456 | .msg_queue_msgsnd = smack_msg_queue_msgsnd, |
2438 | .msg_queue_msgrcv = smack_msg_queue_msgrcv, | 2457 | .msg_queue_msgrcv = smack_msg_queue_msgrcv, |
2439 | 2458 | ||
2440 | .shm_alloc_security = smack_shm_alloc_security, | 2459 | .shm_alloc_security = smack_shm_alloc_security, |
2441 | .shm_free_security = smack_shm_free_security, | 2460 | .shm_free_security = smack_shm_free_security, |
2442 | .shm_associate = smack_shm_associate, | 2461 | .shm_associate = smack_shm_associate, |
2443 | .shm_shmctl = smack_shm_shmctl, | 2462 | .shm_shmctl = smack_shm_shmctl, |
2444 | .shm_shmat = smack_shm_shmat, | 2463 | .shm_shmat = smack_shm_shmat, |
2445 | 2464 | ||
2446 | .sem_alloc_security = smack_sem_alloc_security, | 2465 | .sem_alloc_security = smack_sem_alloc_security, |
2447 | .sem_free_security = smack_sem_free_security, | 2466 | .sem_free_security = smack_sem_free_security, |
2448 | .sem_associate = smack_sem_associate, | 2467 | .sem_associate = smack_sem_associate, |
2449 | .sem_semctl = smack_sem_semctl, | 2468 | .sem_semctl = smack_sem_semctl, |
2450 | .sem_semop = smack_sem_semop, | 2469 | .sem_semop = smack_sem_semop, |
2451 | 2470 | ||
2452 | .netlink_send = cap_netlink_send, | 2471 | .netlink_send = cap_netlink_send, |
2453 | .netlink_recv = cap_netlink_recv, | 2472 | .netlink_recv = cap_netlink_recv, |
2454 | 2473 | ||
2455 | .d_instantiate = smack_d_instantiate, | 2474 | .d_instantiate = smack_d_instantiate, |
2456 | 2475 | ||
2457 | .getprocattr = smack_getprocattr, | 2476 | .getprocattr = smack_getprocattr, |
2458 | .setprocattr = smack_setprocattr, | 2477 | .setprocattr = smack_setprocattr, |
2459 | 2478 | ||
2460 | .unix_stream_connect = smack_unix_stream_connect, | 2479 | .unix_stream_connect = smack_unix_stream_connect, |
2461 | .unix_may_send = smack_unix_may_send, | 2480 | .unix_may_send = smack_unix_may_send, |
2462 | 2481 | ||
2463 | .socket_post_create = smack_socket_post_create, | 2482 | .socket_post_create = smack_socket_post_create, |
2464 | .socket_sock_rcv_skb = smack_socket_sock_rcv_skb, | 2483 | .socket_sock_rcv_skb = smack_socket_sock_rcv_skb, |
2465 | .socket_getpeersec_stream = smack_socket_getpeersec_stream, | 2484 | .socket_getpeersec_stream = smack_socket_getpeersec_stream, |
2466 | .socket_getpeersec_dgram = smack_socket_getpeersec_dgram, | 2485 | .socket_getpeersec_dgram = smack_socket_getpeersec_dgram, |
2467 | .sk_alloc_security = smack_sk_alloc_security, | 2486 | .sk_alloc_security = smack_sk_alloc_security, |
2468 | .sk_free_security = smack_sk_free_security, | 2487 | .sk_free_security = smack_sk_free_security, |
2469 | .sock_graft = smack_sock_graft, | 2488 | .sock_graft = smack_sock_graft, |
2470 | .inet_conn_request = smack_inet_conn_request, | 2489 | .inet_conn_request = smack_inet_conn_request, |
2471 | /* key management security hooks */ | 2490 | /* key management security hooks */ |
2472 | #ifdef CONFIG_KEYS | 2491 | #ifdef CONFIG_KEYS |
2473 | .key_alloc = smack_key_alloc, | 2492 | .key_alloc = smack_key_alloc, |
2474 | .key_free = smack_key_free, | 2493 | .key_free = smack_key_free, |
2475 | .key_permission = smack_key_permission, | 2494 | .key_permission = smack_key_permission, |
2476 | #endif /* CONFIG_KEYS */ | 2495 | #endif /* CONFIG_KEYS */ |
2477 | .secid_to_secctx = smack_secid_to_secctx, | 2496 | .secid_to_secctx = smack_secid_to_secctx, |
2497 | .secctx_to_secid = smack_secctx_to_secid, | ||
2478 | .release_secctx = smack_release_secctx, | 2498 | .release_secctx = smack_release_secctx, |
2479 | }; | 2499 | }; |
2480 | 2500 | ||
2481 | /** | 2501 | /** |
2482 | * smack_init - initialize the smack system | 2502 | * smack_init - initialize the smack system |
2483 | * | 2503 | * |
2484 | * Returns 0 | 2504 | * Returns 0 |
2485 | */ | 2505 | */ |
2486 | static __init int smack_init(void) | 2506 | static __init int smack_init(void) |
2487 | { | 2507 | { |
2488 | printk(KERN_INFO "Smack: Initializing.\n"); | 2508 | printk(KERN_INFO "Smack: Initializing.\n"); |
2489 | 2509 | ||
2490 | /* | 2510 | /* |
2491 | * Set the security state for the initial task. | 2511 | * Set the security state for the initial task. |
2492 | */ | 2512 | */ |
2493 | current->security = &smack_known_floor.smk_known; | 2513 | current->security = &smack_known_floor.smk_known; |
2494 | 2514 | ||
2495 | /* | 2515 | /* |
2496 | * Initialize locks | 2516 | * Initialize locks |
2497 | */ | 2517 | */ |
2498 | spin_lock_init(&smack_known_unset.smk_cipsolock); | 2518 | spin_lock_init(&smack_known_unset.smk_cipsolock); |
2499 | spin_lock_init(&smack_known_huh.smk_cipsolock); | 2519 | spin_lock_init(&smack_known_huh.smk_cipsolock); |
2500 | spin_lock_init(&smack_known_hat.smk_cipsolock); | 2520 | spin_lock_init(&smack_known_hat.smk_cipsolock); |
2501 | spin_lock_init(&smack_known_star.smk_cipsolock); | 2521 | spin_lock_init(&smack_known_star.smk_cipsolock); |
2502 | spin_lock_init(&smack_known_floor.smk_cipsolock); | 2522 | spin_lock_init(&smack_known_floor.smk_cipsolock); |
2503 | spin_lock_init(&smack_known_invalid.smk_cipsolock); | 2523 | spin_lock_init(&smack_known_invalid.smk_cipsolock); |
2504 | 2524 | ||
2505 | /* | 2525 | /* |
2506 | * Register with LSM | 2526 | * Register with LSM |
2507 | */ | 2527 | */ |
2508 | if (register_security(&smack_ops)) | 2528 | if (register_security(&smack_ops)) |
2509 | panic("smack: Unable to register with kernel.\n"); | 2529 | panic("smack: Unable to register with kernel.\n"); |
2510 | 2530 | ||
2511 | return 0; | 2531 | return 0; |
2512 | } | 2532 | } |
2513 | 2533 | ||
2514 | /* | 2534 | /* |
2515 | * Smack requires early initialization in order to label | 2535 | * Smack requires early initialization in order to label |
2516 | * all processes and objects when they are created. | 2536 | * all processes and objects when they are created. |
2517 | */ | 2537 | */ |
security/smack/smackfs.c
1 | /* | 1 | /* |
2 | * Copyright (C) 2007 Casey Schaufler <casey@schaufler-ca.com> | 2 | * Copyright (C) 2007 Casey Schaufler <casey@schaufler-ca.com> |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
5 | * it under the terms of the GNU General Public License as published by | 5 | * it under the terms of the GNU General Public License as published by |
6 | * the Free Software Foundation, version 2. | 6 | * the Free Software Foundation, version 2. |
7 | * | 7 | * |
8 | * Authors: | 8 | * Authors: |
9 | * Casey Schaufler <casey@schaufler-ca.com> | 9 | * Casey Schaufler <casey@schaufler-ca.com> |
10 | * Ahmed S. Darwish <darwish.07@gmail.com> | 10 | * Ahmed S. Darwish <darwish.07@gmail.com> |
11 | * | 11 | * |
12 | * Special thanks to the authors of selinuxfs. | 12 | * Special thanks to the authors of selinuxfs. |
13 | * | 13 | * |
14 | * Karl MacMillan <kmacmillan@tresys.com> | 14 | * Karl MacMillan <kmacmillan@tresys.com> |
15 | * James Morris <jmorris@redhat.com> | 15 | * James Morris <jmorris@redhat.com> |
16 | * | 16 | * |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
20 | #include <linux/vmalloc.h> | 20 | #include <linux/vmalloc.h> |
21 | #include <linux/security.h> | 21 | #include <linux/security.h> |
22 | #include <linux/mutex.h> | 22 | #include <linux/mutex.h> |
23 | #include <net/netlabel.h> | 23 | #include <net/netlabel.h> |
24 | #include <net/cipso_ipv4.h> | 24 | #include <net/cipso_ipv4.h> |
25 | #include <linux/seq_file.h> | 25 | #include <linux/seq_file.h> |
26 | #include <linux/ctype.h> | 26 | #include <linux/ctype.h> |
27 | #include <linux/audit.h> | ||
27 | #include "smack.h" | 28 | #include "smack.h" |
28 | 29 | ||
29 | /* | 30 | /* |
30 | * smackfs pseudo filesystem. | 31 | * smackfs pseudo filesystem. |
31 | */ | 32 | */ |
32 | 33 | ||
33 | enum smk_inos { | 34 | enum smk_inos { |
34 | SMK_ROOT_INO = 2, | 35 | SMK_ROOT_INO = 2, |
35 | SMK_LOAD = 3, /* load policy */ | 36 | SMK_LOAD = 3, /* load policy */ |
36 | SMK_CIPSO = 4, /* load label -> CIPSO mapping */ | 37 | SMK_CIPSO = 4, /* load label -> CIPSO mapping */ |
37 | SMK_DOI = 5, /* CIPSO DOI */ | 38 | SMK_DOI = 5, /* CIPSO DOI */ |
38 | SMK_DIRECT = 6, /* CIPSO level indicating direct label */ | 39 | SMK_DIRECT = 6, /* CIPSO level indicating direct label */ |
39 | SMK_AMBIENT = 7, /* internet ambient label */ | 40 | SMK_AMBIENT = 7, /* internet ambient label */ |
40 | SMK_NLTYPE = 8, /* label scheme to use by default */ | 41 | SMK_NLTYPE = 8, /* label scheme to use by default */ |
41 | }; | 42 | }; |
42 | 43 | ||
43 | /* | 44 | /* |
44 | * List locks | 45 | * List locks |
45 | */ | 46 | */ |
46 | static DEFINE_MUTEX(smack_list_lock); | 47 | static DEFINE_MUTEX(smack_list_lock); |
47 | static DEFINE_MUTEX(smack_cipso_lock); | 48 | static DEFINE_MUTEX(smack_cipso_lock); |
49 | static DEFINE_MUTEX(smack_ambient_lock); | ||
48 | 50 | ||
49 | /* | 51 | /* |
50 | * This is the "ambient" label for network traffic. | 52 | * This is the "ambient" label for network traffic. |
51 | * If it isn't somehow marked, use this. | 53 | * If it isn't somehow marked, use this. |
52 | * It can be reset via smackfs/ambient | 54 | * It can be reset via smackfs/ambient |
53 | */ | 55 | */ |
54 | char *smack_net_ambient = smack_known_floor.smk_known; | 56 | char *smack_net_ambient = smack_known_floor.smk_known; |
55 | 57 | ||
56 | /* | 58 | /* |
57 | * This is the default packet marking scheme for network traffic. | 59 | * This is the default packet marking scheme for network traffic. |
58 | * It can be reset via smackfs/nltype | 60 | * It can be reset via smackfs/nltype |
59 | */ | 61 | */ |
60 | int smack_net_nltype = NETLBL_NLTYPE_CIPSOV4; | 62 | int smack_net_nltype = NETLBL_NLTYPE_CIPSOV4; |
61 | 63 | ||
62 | /* | 64 | /* |
63 | * This is the level in a CIPSO header that indicates a | 65 | * This is the level in a CIPSO header that indicates a |
64 | * smack label is contained directly in the category set. | 66 | * smack label is contained directly in the category set. |
65 | * It can be reset via smackfs/direct | 67 | * It can be reset via smackfs/direct |
66 | */ | 68 | */ |
67 | int smack_cipso_direct = SMACK_CIPSO_DIRECT_DEFAULT; | 69 | int smack_cipso_direct = SMACK_CIPSO_DIRECT_DEFAULT; |
68 | 70 | ||
69 | static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT; | 71 | static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT; |
70 | struct smk_list_entry *smack_list; | 72 | struct smk_list_entry *smack_list; |
71 | 73 | ||
72 | #define SEQ_READ_FINISHED 1 | 74 | #define SEQ_READ_FINISHED 1 |
73 | 75 | ||
74 | /* | 76 | /* |
75 | * Disable concurrent writing open() operations | 77 | * Disable concurrent writing open() operations |
76 | */ | 78 | */ |
77 | static struct semaphore smack_write_sem; | 79 | static struct semaphore smack_write_sem; |
78 | 80 | ||
79 | /* | 81 | /* |
80 | * Values for parsing cipso rules | 82 | * Values for parsing cipso rules |
81 | * SMK_DIGITLEN: Length of a digit field in a rule. | 83 | * SMK_DIGITLEN: Length of a digit field in a rule. |
82 | * SMK_CIPSOMEN: Minimum possible cipso rule length. | 84 | * SMK_CIPSOMEN: Minimum possible cipso rule length. |
83 | */ | 85 | */ |
84 | #define SMK_DIGITLEN 4 | 86 | #define SMK_DIGITLEN 4 |
85 | #define SMK_CIPSOMIN (SMK_MAXLEN + 2 * SMK_DIGITLEN) | 87 | #define SMK_CIPSOMIN (SMK_MAXLEN + 2 * SMK_DIGITLEN) |
86 | 88 | ||
87 | /* | 89 | /* |
88 | * Seq_file read operations for /smack/load | 90 | * Seq_file read operations for /smack/load |
89 | */ | 91 | */ |
90 | 92 | ||
91 | static void *load_seq_start(struct seq_file *s, loff_t *pos) | 93 | static void *load_seq_start(struct seq_file *s, loff_t *pos) |
92 | { | 94 | { |
93 | if (*pos == SEQ_READ_FINISHED) | 95 | if (*pos == SEQ_READ_FINISHED) |
94 | return NULL; | 96 | return NULL; |
95 | 97 | ||
96 | return smack_list; | 98 | return smack_list; |
97 | } | 99 | } |
98 | 100 | ||
99 | static void *load_seq_next(struct seq_file *s, void *v, loff_t *pos) | 101 | static void *load_seq_next(struct seq_file *s, void *v, loff_t *pos) |
100 | { | 102 | { |
101 | struct smk_list_entry *skp = ((struct smk_list_entry *) v)->smk_next; | 103 | struct smk_list_entry *skp = ((struct smk_list_entry *) v)->smk_next; |
102 | 104 | ||
103 | if (skp == NULL) | 105 | if (skp == NULL) |
104 | *pos = SEQ_READ_FINISHED; | 106 | *pos = SEQ_READ_FINISHED; |
105 | 107 | ||
106 | return skp; | 108 | return skp; |
107 | } | 109 | } |
108 | 110 | ||
109 | static int load_seq_show(struct seq_file *s, void *v) | 111 | static int load_seq_show(struct seq_file *s, void *v) |
110 | { | 112 | { |
111 | struct smk_list_entry *slp = (struct smk_list_entry *) v; | 113 | struct smk_list_entry *slp = (struct smk_list_entry *) v; |
112 | struct smack_rule *srp = &slp->smk_rule; | 114 | struct smack_rule *srp = &slp->smk_rule; |
113 | 115 | ||
114 | seq_printf(s, "%s %s", (char *)srp->smk_subject, | 116 | seq_printf(s, "%s %s", (char *)srp->smk_subject, |
115 | (char *)srp->smk_object); | 117 | (char *)srp->smk_object); |
116 | 118 | ||
117 | seq_putc(s, ' '); | 119 | seq_putc(s, ' '); |
118 | 120 | ||
119 | if (srp->smk_access & MAY_READ) | 121 | if (srp->smk_access & MAY_READ) |
120 | seq_putc(s, 'r'); | 122 | seq_putc(s, 'r'); |
121 | if (srp->smk_access & MAY_WRITE) | 123 | if (srp->smk_access & MAY_WRITE) |
122 | seq_putc(s, 'w'); | 124 | seq_putc(s, 'w'); |
123 | if (srp->smk_access & MAY_EXEC) | 125 | if (srp->smk_access & MAY_EXEC) |
124 | seq_putc(s, 'x'); | 126 | seq_putc(s, 'x'); |
125 | if (srp->smk_access & MAY_APPEND) | 127 | if (srp->smk_access & MAY_APPEND) |
126 | seq_putc(s, 'a'); | 128 | seq_putc(s, 'a'); |
127 | if (srp->smk_access == 0) | 129 | if (srp->smk_access == 0) |
128 | seq_putc(s, '-'); | 130 | seq_putc(s, '-'); |
129 | 131 | ||
130 | seq_putc(s, '\n'); | 132 | seq_putc(s, '\n'); |
131 | 133 | ||
132 | return 0; | 134 | return 0; |
133 | } | 135 | } |
134 | 136 | ||
135 | static void load_seq_stop(struct seq_file *s, void *v) | 137 | static void load_seq_stop(struct seq_file *s, void *v) |
136 | { | 138 | { |
137 | /* No-op */ | 139 | /* No-op */ |
138 | } | 140 | } |
139 | 141 | ||
140 | static struct seq_operations load_seq_ops = { | 142 | static struct seq_operations load_seq_ops = { |
141 | .start = load_seq_start, | 143 | .start = load_seq_start, |
142 | .next = load_seq_next, | 144 | .next = load_seq_next, |
143 | .show = load_seq_show, | 145 | .show = load_seq_show, |
144 | .stop = load_seq_stop, | 146 | .stop = load_seq_stop, |
145 | }; | 147 | }; |
146 | 148 | ||
147 | /** | 149 | /** |
148 | * smk_open_load - open() for /smack/load | 150 | * smk_open_load - open() for /smack/load |
149 | * @inode: inode structure representing file | 151 | * @inode: inode structure representing file |
150 | * @file: "load" file pointer | 152 | * @file: "load" file pointer |
151 | * | 153 | * |
152 | * For reading, use load_seq_* seq_file reading operations. | 154 | * For reading, use load_seq_* seq_file reading operations. |
153 | */ | 155 | */ |
154 | static int smk_open_load(struct inode *inode, struct file *file) | 156 | static int smk_open_load(struct inode *inode, struct file *file) |
155 | { | 157 | { |
156 | if ((file->f_flags & O_ACCMODE) == O_RDONLY) | 158 | if ((file->f_flags & O_ACCMODE) == O_RDONLY) |
157 | return seq_open(file, &load_seq_ops); | 159 | return seq_open(file, &load_seq_ops); |
158 | 160 | ||
159 | if (down_interruptible(&smack_write_sem)) | 161 | if (down_interruptible(&smack_write_sem)) |
160 | return -ERESTARTSYS; | 162 | return -ERESTARTSYS; |
161 | 163 | ||
162 | return 0; | 164 | return 0; |
163 | } | 165 | } |
164 | 166 | ||
165 | /** | 167 | /** |
166 | * smk_release_load - release() for /smack/load | 168 | * smk_release_load - release() for /smack/load |
167 | * @inode: inode structure representing file | 169 | * @inode: inode structure representing file |
168 | * @file: "load" file pointer | 170 | * @file: "load" file pointer |
169 | * | 171 | * |
170 | * For a reading session, use the seq_file release | 172 | * For a reading session, use the seq_file release |
171 | * implementation. | 173 | * implementation. |
172 | * Otherwise, we are at the end of a writing session so | 174 | * Otherwise, we are at the end of a writing session so |
173 | * clean everything up. | 175 | * clean everything up. |
174 | */ | 176 | */ |
175 | static int smk_release_load(struct inode *inode, struct file *file) | 177 | static int smk_release_load(struct inode *inode, struct file *file) |
176 | { | 178 | { |
177 | if ((file->f_flags & O_ACCMODE) == O_RDONLY) | 179 | if ((file->f_flags & O_ACCMODE) == O_RDONLY) |
178 | return seq_release(inode, file); | 180 | return seq_release(inode, file); |
179 | 181 | ||
180 | up(&smack_write_sem); | 182 | up(&smack_write_sem); |
181 | return 0; | 183 | return 0; |
182 | } | 184 | } |
183 | 185 | ||
184 | /** | 186 | /** |
185 | * smk_set_access - add a rule to the rule list | 187 | * smk_set_access - add a rule to the rule list |
186 | * @srp: the new rule to add | 188 | * @srp: the new rule to add |
187 | * | 189 | * |
188 | * Looks through the current subject/object/access list for | 190 | * Looks through the current subject/object/access list for |
189 | * the subject/object pair and replaces the access that was | 191 | * the subject/object pair and replaces the access that was |
190 | * there. If the pair isn't found add it with the specified | 192 | * there. If the pair isn't found add it with the specified |
191 | * access. | 193 | * access. |
192 | */ | 194 | */ |
193 | static void smk_set_access(struct smack_rule *srp) | 195 | static void smk_set_access(struct smack_rule *srp) |
194 | { | 196 | { |
195 | struct smk_list_entry *sp; | 197 | struct smk_list_entry *sp; |
196 | struct smk_list_entry *newp; | 198 | struct smk_list_entry *newp; |
197 | 199 | ||
198 | mutex_lock(&smack_list_lock); | 200 | mutex_lock(&smack_list_lock); |
199 | 201 | ||
200 | for (sp = smack_list; sp != NULL; sp = sp->smk_next) | 202 | for (sp = smack_list; sp != NULL; sp = sp->smk_next) |
201 | if (sp->smk_rule.smk_subject == srp->smk_subject && | 203 | if (sp->smk_rule.smk_subject == srp->smk_subject && |
202 | sp->smk_rule.smk_object == srp->smk_object) { | 204 | sp->smk_rule.smk_object == srp->smk_object) { |
203 | sp->smk_rule.smk_access = srp->smk_access; | 205 | sp->smk_rule.smk_access = srp->smk_access; |
204 | break; | 206 | break; |
205 | } | 207 | } |
206 | 208 | ||
207 | if (sp == NULL) { | 209 | if (sp == NULL) { |
208 | newp = kzalloc(sizeof(struct smk_list_entry), GFP_KERNEL); | 210 | newp = kzalloc(sizeof(struct smk_list_entry), GFP_KERNEL); |
209 | newp->smk_rule = *srp; | 211 | newp->smk_rule = *srp; |
210 | newp->smk_next = smack_list; | 212 | newp->smk_next = smack_list; |
211 | smack_list = newp; | 213 | smack_list = newp; |
212 | } | 214 | } |
213 | 215 | ||
214 | mutex_unlock(&smack_list_lock); | 216 | mutex_unlock(&smack_list_lock); |
215 | 217 | ||
216 | return; | 218 | return; |
217 | } | 219 | } |
218 | 220 | ||
219 | /** | 221 | /** |
220 | * smk_write_load - write() for /smack/load | 222 | * smk_write_load - write() for /smack/load |
221 | * @filp: file pointer, not actually used | 223 | * @filp: file pointer, not actually used |
222 | * @buf: where to get the data from | 224 | * @buf: where to get the data from |
223 | * @count: bytes sent | 225 | * @count: bytes sent |
224 | * @ppos: where to start - must be 0 | 226 | * @ppos: where to start - must be 0 |
225 | * | 227 | * |
226 | * Get one smack access rule from above. | 228 | * Get one smack access rule from above. |
227 | * The format is exactly: | 229 | * The format is exactly: |
228 | * char subject[SMK_LABELLEN] | 230 | * char subject[SMK_LABELLEN] |
229 | * char object[SMK_LABELLEN] | 231 | * char object[SMK_LABELLEN] |
230 | * char access[SMK_ACCESSKINDS] | 232 | * char access[SMK_ACCESSKINDS] |
231 | * | 233 | * |
232 | * Anything following is commentary and ignored. | 234 | * Anything following is commentary and ignored. |
233 | * | 235 | * |
234 | * writes must be SMK_LABELLEN+SMK_LABELLEN+4 bytes. | 236 | * writes must be SMK_LABELLEN+SMK_LABELLEN+4 bytes. |
235 | */ | 237 | */ |
236 | #define MINIMUM_LOAD (SMK_LABELLEN + SMK_LABELLEN + SMK_ACCESSKINDS) | 238 | #define MINIMUM_LOAD (SMK_LABELLEN + SMK_LABELLEN + SMK_ACCESSKINDS) |
237 | 239 | ||
238 | static ssize_t smk_write_load(struct file *file, const char __user *buf, | 240 | static ssize_t smk_write_load(struct file *file, const char __user *buf, |
239 | size_t count, loff_t *ppos) | 241 | size_t count, loff_t *ppos) |
240 | { | 242 | { |
241 | struct smack_rule rule; | 243 | struct smack_rule rule; |
242 | char *data; | 244 | char *data; |
243 | int rc = -EINVAL; | 245 | int rc = -EINVAL; |
244 | 246 | ||
245 | /* | 247 | /* |
246 | * Must have privilege. | 248 | * Must have privilege. |
247 | * No partial writes. | 249 | * No partial writes. |
248 | * Enough data must be present. | 250 | * Enough data must be present. |
249 | */ | 251 | */ |
250 | if (!capable(CAP_MAC_ADMIN)) | 252 | if (!capable(CAP_MAC_ADMIN)) |
251 | return -EPERM; | 253 | return -EPERM; |
252 | if (*ppos != 0) | 254 | if (*ppos != 0) |
253 | return -EINVAL; | 255 | return -EINVAL; |
254 | if (count < MINIMUM_LOAD) | 256 | if (count < MINIMUM_LOAD) |
255 | return -EINVAL; | 257 | return -EINVAL; |
256 | 258 | ||
257 | data = kzalloc(count, GFP_KERNEL); | 259 | data = kzalloc(count, GFP_KERNEL); |
258 | if (data == NULL) | 260 | if (data == NULL) |
259 | return -ENOMEM; | 261 | return -ENOMEM; |
260 | 262 | ||
261 | if (copy_from_user(data, buf, count) != 0) { | 263 | if (copy_from_user(data, buf, count) != 0) { |
262 | rc = -EFAULT; | 264 | rc = -EFAULT; |
263 | goto out; | 265 | goto out; |
264 | } | 266 | } |
265 | 267 | ||
266 | rule.smk_subject = smk_import(data, 0); | 268 | rule.smk_subject = smk_import(data, 0); |
267 | if (rule.smk_subject == NULL) | 269 | if (rule.smk_subject == NULL) |
268 | goto out; | 270 | goto out; |
269 | 271 | ||
270 | rule.smk_object = smk_import(data + SMK_LABELLEN, 0); | 272 | rule.smk_object = smk_import(data + SMK_LABELLEN, 0); |
271 | if (rule.smk_object == NULL) | 273 | if (rule.smk_object == NULL) |
272 | goto out; | 274 | goto out; |
273 | 275 | ||
274 | rule.smk_access = 0; | 276 | rule.smk_access = 0; |
275 | 277 | ||
276 | switch (data[SMK_LABELLEN + SMK_LABELLEN]) { | 278 | switch (data[SMK_LABELLEN + SMK_LABELLEN]) { |
277 | case '-': | 279 | case '-': |
278 | break; | 280 | break; |
279 | case 'r': | 281 | case 'r': |
280 | case 'R': | 282 | case 'R': |
281 | rule.smk_access |= MAY_READ; | 283 | rule.smk_access |= MAY_READ; |
282 | break; | 284 | break; |
283 | default: | 285 | default: |
284 | goto out; | 286 | goto out; |
285 | } | 287 | } |
286 | 288 | ||
287 | switch (data[SMK_LABELLEN + SMK_LABELLEN + 1]) { | 289 | switch (data[SMK_LABELLEN + SMK_LABELLEN + 1]) { |
288 | case '-': | 290 | case '-': |
289 | break; | 291 | break; |
290 | case 'w': | 292 | case 'w': |
291 | case 'W': | 293 | case 'W': |
292 | rule.smk_access |= MAY_WRITE; | 294 | rule.smk_access |= MAY_WRITE; |
293 | break; | 295 | break; |
294 | default: | 296 | default: |
295 | goto out; | 297 | goto out; |
296 | } | 298 | } |
297 | 299 | ||
298 | switch (data[SMK_LABELLEN + SMK_LABELLEN + 2]) { | 300 | switch (data[SMK_LABELLEN + SMK_LABELLEN + 2]) { |
299 | case '-': | 301 | case '-': |
300 | break; | 302 | break; |
301 | case 'x': | 303 | case 'x': |
302 | case 'X': | 304 | case 'X': |
303 | rule.smk_access |= MAY_EXEC; | 305 | rule.smk_access |= MAY_EXEC; |
304 | break; | 306 | break; |
305 | default: | 307 | default: |
306 | goto out; | 308 | goto out; |
307 | } | 309 | } |
308 | 310 | ||
309 | switch (data[SMK_LABELLEN + SMK_LABELLEN + 3]) { | 311 | switch (data[SMK_LABELLEN + SMK_LABELLEN + 3]) { |
310 | case '-': | 312 | case '-': |
311 | break; | 313 | break; |
312 | case 'a': | 314 | case 'a': |
313 | case 'A': | 315 | case 'A': |
314 | rule.smk_access |= MAY_READ; | 316 | rule.smk_access |= MAY_READ; |
315 | break; | 317 | break; |
316 | default: | 318 | default: |
317 | goto out; | 319 | goto out; |
318 | } | 320 | } |
319 | 321 | ||
320 | smk_set_access(&rule); | 322 | smk_set_access(&rule); |
321 | rc = count; | 323 | rc = count; |
322 | 324 | ||
323 | out: | 325 | out: |
324 | kfree(data); | 326 | kfree(data); |
325 | return rc; | 327 | return rc; |
326 | } | 328 | } |
327 | 329 | ||
328 | static const struct file_operations smk_load_ops = { | 330 | static const struct file_operations smk_load_ops = { |
329 | .open = smk_open_load, | 331 | .open = smk_open_load, |
330 | .read = seq_read, | 332 | .read = seq_read, |
331 | .llseek = seq_lseek, | 333 | .llseek = seq_lseek, |
332 | .write = smk_write_load, | 334 | .write = smk_write_load, |
333 | .release = smk_release_load, | 335 | .release = smk_release_load, |
334 | }; | 336 | }; |
335 | 337 | ||
336 | /** | 338 | /** |
337 | * smk_cipso_doi - initialize the CIPSO domain | 339 | * smk_cipso_doi - initialize the CIPSO domain |
338 | */ | 340 | */ |
339 | void smk_cipso_doi(void) | 341 | void smk_cipso_doi(void) |
340 | { | 342 | { |
341 | int rc; | 343 | int rc; |
342 | struct cipso_v4_doi *doip; | 344 | struct cipso_v4_doi *doip; |
343 | struct netlbl_audit audit_info; | 345 | struct netlbl_audit audit_info; |
344 | 346 | ||
347 | audit_info.loginuid = audit_get_loginuid(current); | ||
348 | audit_info.secid = smack_to_secid(current->security); | ||
349 | |||
345 | rc = netlbl_cfg_map_del(NULL, &audit_info); | 350 | rc = netlbl_cfg_map_del(NULL, &audit_info); |
346 | if (rc != 0) | 351 | if (rc != 0) |
347 | printk(KERN_WARNING "%s:%d remove rc = %d\n", | 352 | printk(KERN_WARNING "%s:%d remove rc = %d\n", |
348 | __func__, __LINE__, rc); | 353 | __func__, __LINE__, rc); |
349 | 354 | ||
350 | doip = kmalloc(sizeof(struct cipso_v4_doi), GFP_KERNEL); | 355 | doip = kmalloc(sizeof(struct cipso_v4_doi), GFP_KERNEL); |
351 | if (doip == NULL) | 356 | if (doip == NULL) |
352 | panic("smack: Failed to initialize cipso DOI.\n"); | 357 | panic("smack: Failed to initialize cipso DOI.\n"); |
353 | doip->map.std = NULL; | 358 | doip->map.std = NULL; |
354 | doip->doi = smk_cipso_doi_value; | 359 | doip->doi = smk_cipso_doi_value; |
355 | doip->type = CIPSO_V4_MAP_PASS; | 360 | doip->type = CIPSO_V4_MAP_PASS; |
356 | doip->tags[0] = CIPSO_V4_TAG_RBITMAP; | 361 | doip->tags[0] = CIPSO_V4_TAG_RBITMAP; |
357 | for (rc = 1; rc < CIPSO_V4_TAG_MAXCNT; rc++) | 362 | for (rc = 1; rc < CIPSO_V4_TAG_MAXCNT; rc++) |
358 | doip->tags[rc] = CIPSO_V4_TAG_INVALID; | 363 | doip->tags[rc] = CIPSO_V4_TAG_INVALID; |
359 | 364 | ||
360 | rc = netlbl_cfg_cipsov4_add_map(doip, NULL, &audit_info); | 365 | rc = netlbl_cfg_cipsov4_add_map(doip, NULL, &audit_info); |
361 | if (rc != 0) | 366 | if (rc != 0) |
362 | printk(KERN_WARNING "%s:%d add rc = %d\n", | 367 | printk(KERN_WARNING "%s:%d add rc = %d\n", |
363 | __func__, __LINE__, rc); | 368 | __func__, __LINE__, rc); |
364 | } | 369 | } |
365 | 370 | ||
371 | /** | ||
372 | * smk_unlbl_ambient - initialize the unlabeled domain | ||
373 | */ | ||
374 | void smk_unlbl_ambient(char *oldambient) | ||
375 | { | ||
376 | int rc; | ||
377 | struct netlbl_audit audit_info; | ||
378 | |||
379 | audit_info.loginuid = audit_get_loginuid(current); | ||
380 | audit_info.secid = smack_to_secid(current->security); | ||
381 | |||
382 | if (oldambient != NULL) { | ||
383 | rc = netlbl_cfg_map_del(oldambient, &audit_info); | ||
384 | if (rc != 0) | ||
385 | printk(KERN_WARNING "%s:%d remove rc = %d\n", | ||
386 | __func__, __LINE__, rc); | ||
387 | } | ||
388 | |||
389 | rc = netlbl_cfg_unlbl_add_map(smack_net_ambient, &audit_info); | ||
390 | if (rc != 0) | ||
391 | printk(KERN_WARNING "%s:%d add rc = %d\n", | ||
392 | __func__, __LINE__, rc); | ||
393 | } | ||
394 | |||
366 | /* | 395 | /* |
367 | * Seq_file read operations for /smack/cipso | 396 | * Seq_file read operations for /smack/cipso |
368 | */ | 397 | */ |
369 | 398 | ||
370 | static void *cipso_seq_start(struct seq_file *s, loff_t *pos) | 399 | static void *cipso_seq_start(struct seq_file *s, loff_t *pos) |
371 | { | 400 | { |
372 | if (*pos == SEQ_READ_FINISHED) | 401 | if (*pos == SEQ_READ_FINISHED) |
373 | return NULL; | 402 | return NULL; |
374 | 403 | ||
375 | return smack_known; | 404 | return smack_known; |
376 | } | 405 | } |
377 | 406 | ||
378 | static void *cipso_seq_next(struct seq_file *s, void *v, loff_t *pos) | 407 | static void *cipso_seq_next(struct seq_file *s, void *v, loff_t *pos) |
379 | { | 408 | { |
380 | struct smack_known *skp = ((struct smack_known *) v)->smk_next; | 409 | struct smack_known *skp = ((struct smack_known *) v)->smk_next; |
381 | 410 | ||
382 | /* | 411 | /* |
383 | * Omit labels with no associated cipso value | 412 | * Omit labels with no associated cipso value |
384 | */ | 413 | */ |
385 | while (skp != NULL && !skp->smk_cipso) | 414 | while (skp != NULL && !skp->smk_cipso) |
386 | skp = skp->smk_next; | 415 | skp = skp->smk_next; |
387 | 416 | ||
388 | if (skp == NULL) | 417 | if (skp == NULL) |
389 | *pos = SEQ_READ_FINISHED; | 418 | *pos = SEQ_READ_FINISHED; |
390 | 419 | ||
391 | return skp; | 420 | return skp; |
392 | } | 421 | } |
393 | 422 | ||
394 | /* | 423 | /* |
395 | * Print cipso labels in format: | 424 | * Print cipso labels in format: |
396 | * label level[/cat[,cat]] | 425 | * label level[/cat[,cat]] |
397 | */ | 426 | */ |
398 | static int cipso_seq_show(struct seq_file *s, void *v) | 427 | static int cipso_seq_show(struct seq_file *s, void *v) |
399 | { | 428 | { |
400 | struct smack_known *skp = (struct smack_known *) v; | 429 | struct smack_known *skp = (struct smack_known *) v; |
401 | struct smack_cipso *scp = skp->smk_cipso; | 430 | struct smack_cipso *scp = skp->smk_cipso; |
402 | char *cbp; | 431 | char *cbp; |
403 | char sep = '/'; | 432 | char sep = '/'; |
404 | int cat = 1; | 433 | int cat = 1; |
405 | int i; | 434 | int i; |
406 | unsigned char m; | 435 | unsigned char m; |
407 | 436 | ||
408 | if (scp == NULL) | 437 | if (scp == NULL) |
409 | return 0; | 438 | return 0; |
410 | 439 | ||
411 | seq_printf(s, "%s %3d", (char *)&skp->smk_known, scp->smk_level); | 440 | seq_printf(s, "%s %3d", (char *)&skp->smk_known, scp->smk_level); |
412 | 441 | ||
413 | cbp = scp->smk_catset; | 442 | cbp = scp->smk_catset; |
414 | for (i = 0; i < SMK_LABELLEN; i++) | 443 | for (i = 0; i < SMK_LABELLEN; i++) |
415 | for (m = 0x80; m != 0; m >>= 1) { | 444 | for (m = 0x80; m != 0; m >>= 1) { |
416 | if (m & cbp[i]) { | 445 | if (m & cbp[i]) { |
417 | seq_printf(s, "%c%d", sep, cat); | 446 | seq_printf(s, "%c%d", sep, cat); |
418 | sep = ','; | 447 | sep = ','; |
419 | } | 448 | } |
420 | cat++; | 449 | cat++; |
421 | } | 450 | } |
422 | 451 | ||
423 | seq_putc(s, '\n'); | 452 | seq_putc(s, '\n'); |
424 | 453 | ||
425 | return 0; | 454 | return 0; |
426 | } | 455 | } |
427 | 456 | ||
428 | static void cipso_seq_stop(struct seq_file *s, void *v) | 457 | static void cipso_seq_stop(struct seq_file *s, void *v) |
429 | { | 458 | { |
430 | /* No-op */ | 459 | /* No-op */ |
431 | } | 460 | } |
432 | 461 | ||
433 | static struct seq_operations cipso_seq_ops = { | 462 | static struct seq_operations cipso_seq_ops = { |
434 | .start = cipso_seq_start, | 463 | .start = cipso_seq_start, |
435 | .stop = cipso_seq_stop, | 464 | .stop = cipso_seq_stop, |
436 | .next = cipso_seq_next, | 465 | .next = cipso_seq_next, |
437 | .show = cipso_seq_show, | 466 | .show = cipso_seq_show, |
438 | }; | 467 | }; |
439 | 468 | ||
440 | /** | 469 | /** |
441 | * smk_open_cipso - open() for /smack/cipso | 470 | * smk_open_cipso - open() for /smack/cipso |
442 | * @inode: inode structure representing file | 471 | * @inode: inode structure representing file |
443 | * @file: "cipso" file pointer | 472 | * @file: "cipso" file pointer |
444 | * | 473 | * |
445 | * Connect our cipso_seq_* operations with /smack/cipso | 474 | * Connect our cipso_seq_* operations with /smack/cipso |
446 | * file_operations | 475 | * file_operations |
447 | */ | 476 | */ |
448 | static int smk_open_cipso(struct inode *inode, struct file *file) | 477 | static int smk_open_cipso(struct inode *inode, struct file *file) |
449 | { | 478 | { |
450 | return seq_open(file, &cipso_seq_ops); | 479 | return seq_open(file, &cipso_seq_ops); |
451 | } | 480 | } |
452 | 481 | ||
453 | /** | 482 | /** |
454 | * smk_write_cipso - write() for /smack/cipso | 483 | * smk_write_cipso - write() for /smack/cipso |
455 | * @filp: file pointer, not actually used | 484 | * @filp: file pointer, not actually used |
456 | * @buf: where to get the data from | 485 | * @buf: where to get the data from |
457 | * @count: bytes sent | 486 | * @count: bytes sent |
458 | * @ppos: where to start | 487 | * @ppos: where to start |
459 | * | 488 | * |
460 | * Accepts only one cipso rule per write call. | 489 | * Accepts only one cipso rule per write call. |
461 | * Returns number of bytes written or error code, as appropriate | 490 | * Returns number of bytes written or error code, as appropriate |
462 | */ | 491 | */ |
463 | static ssize_t smk_write_cipso(struct file *file, const char __user *buf, | 492 | static ssize_t smk_write_cipso(struct file *file, const char __user *buf, |
464 | size_t count, loff_t *ppos) | 493 | size_t count, loff_t *ppos) |
465 | { | 494 | { |
466 | struct smack_known *skp; | 495 | struct smack_known *skp; |
467 | struct smack_cipso *scp = NULL; | 496 | struct smack_cipso *scp = NULL; |
468 | char mapcatset[SMK_LABELLEN]; | 497 | char mapcatset[SMK_LABELLEN]; |
469 | int maplevel; | 498 | int maplevel; |
470 | int cat; | 499 | int cat; |
471 | int catlen; | 500 | int catlen; |
472 | ssize_t rc = -EINVAL; | 501 | ssize_t rc = -EINVAL; |
473 | char *data = NULL; | 502 | char *data = NULL; |
474 | char *rule; | 503 | char *rule; |
475 | int ret; | 504 | int ret; |
476 | int i; | 505 | int i; |
477 | 506 | ||
478 | /* | 507 | /* |
479 | * Must have privilege. | 508 | * Must have privilege. |
480 | * No partial writes. | 509 | * No partial writes. |
481 | * Enough data must be present. | 510 | * Enough data must be present. |
482 | */ | 511 | */ |
483 | if (!capable(CAP_MAC_ADMIN)) | 512 | if (!capable(CAP_MAC_ADMIN)) |
484 | return -EPERM; | 513 | return -EPERM; |
485 | if (*ppos != 0) | 514 | if (*ppos != 0) |
486 | return -EINVAL; | 515 | return -EINVAL; |
487 | if (count <= SMK_CIPSOMIN) | 516 | if (count <= SMK_CIPSOMIN) |
488 | return -EINVAL; | 517 | return -EINVAL; |
489 | 518 | ||
490 | data = kzalloc(count + 1, GFP_KERNEL); | 519 | data = kzalloc(count + 1, GFP_KERNEL); |
491 | if (data == NULL) | 520 | if (data == NULL) |
492 | return -ENOMEM; | 521 | return -ENOMEM; |
493 | 522 | ||
494 | if (copy_from_user(data, buf, count) != 0) { | 523 | if (copy_from_user(data, buf, count) != 0) { |
495 | rc = -EFAULT; | 524 | rc = -EFAULT; |
496 | goto unlockedout; | 525 | goto unlockedout; |
497 | } | 526 | } |
498 | 527 | ||
499 | data[count] = '\0'; | 528 | data[count] = '\0'; |
500 | rule = data; | 529 | rule = data; |
501 | /* | 530 | /* |
502 | * Only allow one writer at a time. Writes should be | 531 | * Only allow one writer at a time. Writes should be |
503 | * quite rare and small in any case. | 532 | * quite rare and small in any case. |
504 | */ | 533 | */ |
505 | mutex_lock(&smack_cipso_lock); | 534 | mutex_lock(&smack_cipso_lock); |
506 | 535 | ||
507 | skp = smk_import_entry(rule, 0); | 536 | skp = smk_import_entry(rule, 0); |
508 | if (skp == NULL) | 537 | if (skp == NULL) |
509 | goto out; | 538 | goto out; |
510 | 539 | ||
511 | rule += SMK_LABELLEN;; | 540 | rule += SMK_LABELLEN;; |
512 | ret = sscanf(rule, "%d", &maplevel); | 541 | ret = sscanf(rule, "%d", &maplevel); |
513 | if (ret != 1 || maplevel > SMACK_CIPSO_MAXLEVEL) | 542 | if (ret != 1 || maplevel > SMACK_CIPSO_MAXLEVEL) |
514 | goto out; | 543 | goto out; |
515 | 544 | ||
516 | rule += SMK_DIGITLEN; | 545 | rule += SMK_DIGITLEN; |
517 | ret = sscanf(rule, "%d", &catlen); | 546 | ret = sscanf(rule, "%d", &catlen); |
518 | if (ret != 1 || catlen > SMACK_CIPSO_MAXCATNUM) | 547 | if (ret != 1 || catlen > SMACK_CIPSO_MAXCATNUM) |
519 | goto out; | 548 | goto out; |
520 | 549 | ||
521 | if (count <= (SMK_CIPSOMIN + catlen * SMK_DIGITLEN)) | 550 | if (count <= (SMK_CIPSOMIN + catlen * SMK_DIGITLEN)) |
522 | goto out; | 551 | goto out; |
523 | 552 | ||
524 | memset(mapcatset, 0, sizeof(mapcatset)); | 553 | memset(mapcatset, 0, sizeof(mapcatset)); |
525 | 554 | ||
526 | for (i = 0; i < catlen; i++) { | 555 | for (i = 0; i < catlen; i++) { |
527 | rule += SMK_DIGITLEN; | 556 | rule += SMK_DIGITLEN; |
528 | ret = sscanf(rule, "%d", &cat); | 557 | ret = sscanf(rule, "%d", &cat); |
529 | if (ret != 1 || cat > SMACK_CIPSO_MAXCATVAL) | 558 | if (ret != 1 || cat > SMACK_CIPSO_MAXCATVAL) |
530 | goto out; | 559 | goto out; |
531 | 560 | ||
532 | smack_catset_bit(cat, mapcatset); | 561 | smack_catset_bit(cat, mapcatset); |
533 | } | 562 | } |
534 | 563 | ||
535 | if (skp->smk_cipso == NULL) { | 564 | if (skp->smk_cipso == NULL) { |
536 | scp = kzalloc(sizeof(struct smack_cipso), GFP_KERNEL); | 565 | scp = kzalloc(sizeof(struct smack_cipso), GFP_KERNEL); |
537 | if (scp == NULL) { | 566 | if (scp == NULL) { |
538 | rc = -ENOMEM; | 567 | rc = -ENOMEM; |
539 | goto out; | 568 | goto out; |
540 | } | 569 | } |
541 | } | 570 | } |
542 | 571 | ||
543 | spin_lock_bh(&skp->smk_cipsolock); | 572 | spin_lock_bh(&skp->smk_cipsolock); |
544 | 573 | ||
545 | if (scp == NULL) | 574 | if (scp == NULL) |
546 | scp = skp->smk_cipso; | 575 | scp = skp->smk_cipso; |
547 | else | 576 | else |
548 | skp->smk_cipso = scp; | 577 | skp->smk_cipso = scp; |
549 | 578 | ||
550 | scp->smk_level = maplevel; | 579 | scp->smk_level = maplevel; |
551 | memcpy(scp->smk_catset, mapcatset, sizeof(mapcatset)); | 580 | memcpy(scp->smk_catset, mapcatset, sizeof(mapcatset)); |
552 | 581 | ||
553 | spin_unlock_bh(&skp->smk_cipsolock); | 582 | spin_unlock_bh(&skp->smk_cipsolock); |
554 | 583 | ||
555 | rc = count; | 584 | rc = count; |
556 | out: | 585 | out: |
557 | mutex_unlock(&smack_cipso_lock); | 586 | mutex_unlock(&smack_cipso_lock); |
558 | unlockedout: | 587 | unlockedout: |
559 | kfree(data); | 588 | kfree(data); |
560 | return rc; | 589 | return rc; |
561 | } | 590 | } |
562 | 591 | ||
563 | static const struct file_operations smk_cipso_ops = { | 592 | static const struct file_operations smk_cipso_ops = { |
564 | .open = smk_open_cipso, | 593 | .open = smk_open_cipso, |
565 | .read = seq_read, | 594 | .read = seq_read, |
566 | .llseek = seq_lseek, | 595 | .llseek = seq_lseek, |
567 | .write = smk_write_cipso, | 596 | .write = smk_write_cipso, |
568 | .release = seq_release, | 597 | .release = seq_release, |
569 | }; | 598 | }; |
570 | 599 | ||
571 | /** | 600 | /** |
572 | * smk_read_doi - read() for /smack/doi | 601 | * smk_read_doi - read() for /smack/doi |
573 | * @filp: file pointer, not actually used | 602 | * @filp: file pointer, not actually used |
574 | * @buf: where to put the result | 603 | * @buf: where to put the result |
575 | * @count: maximum to send along | 604 | * @count: maximum to send along |
576 | * @ppos: where to start | 605 | * @ppos: where to start |
577 | * | 606 | * |
578 | * Returns number of bytes read or error code, as appropriate | 607 | * Returns number of bytes read or error code, as appropriate |
579 | */ | 608 | */ |
580 | static ssize_t smk_read_doi(struct file *filp, char __user *buf, | 609 | static ssize_t smk_read_doi(struct file *filp, char __user *buf, |
581 | size_t count, loff_t *ppos) | 610 | size_t count, loff_t *ppos) |
582 | { | 611 | { |
583 | char temp[80]; | 612 | char temp[80]; |
584 | ssize_t rc; | 613 | ssize_t rc; |
585 | 614 | ||
586 | if (*ppos != 0) | 615 | if (*ppos != 0) |
587 | return 0; | 616 | return 0; |
588 | 617 | ||
589 | sprintf(temp, "%d", smk_cipso_doi_value); | 618 | sprintf(temp, "%d", smk_cipso_doi_value); |
590 | rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp)); | 619 | rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp)); |
591 | 620 | ||
592 | return rc; | 621 | return rc; |
593 | } | 622 | } |
594 | 623 | ||
595 | /** | 624 | /** |
596 | * smk_write_doi - write() for /smack/doi | 625 | * smk_write_doi - write() for /smack/doi |
597 | * @filp: file pointer, not actually used | 626 | * @filp: file pointer, not actually used |
598 | * @buf: where to get the data from | 627 | * @buf: where to get the data from |
599 | * @count: bytes sent | 628 | * @count: bytes sent |
600 | * @ppos: where to start | 629 | * @ppos: where to start |
601 | * | 630 | * |
602 | * Returns number of bytes written or error code, as appropriate | 631 | * Returns number of bytes written or error code, as appropriate |
603 | */ | 632 | */ |
604 | static ssize_t smk_write_doi(struct file *file, const char __user *buf, | 633 | static ssize_t smk_write_doi(struct file *file, const char __user *buf, |
605 | size_t count, loff_t *ppos) | 634 | size_t count, loff_t *ppos) |
606 | { | 635 | { |
607 | char temp[80]; | 636 | char temp[80]; |
608 | int i; | 637 | int i; |
609 | 638 | ||
610 | if (!capable(CAP_MAC_ADMIN)) | 639 | if (!capable(CAP_MAC_ADMIN)) |
611 | return -EPERM; | 640 | return -EPERM; |
612 | 641 | ||
613 | if (count >= sizeof(temp) || count == 0) | 642 | if (count >= sizeof(temp) || count == 0) |
614 | return -EINVAL; | 643 | return -EINVAL; |
615 | 644 | ||
616 | if (copy_from_user(temp, buf, count) != 0) | 645 | if (copy_from_user(temp, buf, count) != 0) |
617 | return -EFAULT; | 646 | return -EFAULT; |
618 | 647 | ||
619 | temp[count] = '\0'; | 648 | temp[count] = '\0'; |
620 | 649 | ||
621 | if (sscanf(temp, "%d", &i) != 1) | 650 | if (sscanf(temp, "%d", &i) != 1) |
622 | return -EINVAL; | 651 | return -EINVAL; |
623 | 652 | ||
624 | smk_cipso_doi_value = i; | 653 | smk_cipso_doi_value = i; |
625 | 654 | ||
626 | smk_cipso_doi(); | 655 | smk_cipso_doi(); |
627 | 656 | ||
628 | return count; | 657 | return count; |
629 | } | 658 | } |
630 | 659 | ||
631 | static const struct file_operations smk_doi_ops = { | 660 | static const struct file_operations smk_doi_ops = { |
632 | .read = smk_read_doi, | 661 | .read = smk_read_doi, |
633 | .write = smk_write_doi, | 662 | .write = smk_write_doi, |
634 | }; | 663 | }; |
635 | 664 | ||
636 | /** | 665 | /** |
637 | * smk_read_direct - read() for /smack/direct | 666 | * smk_read_direct - read() for /smack/direct |
638 | * @filp: file pointer, not actually used | 667 | * @filp: file pointer, not actually used |
639 | * @buf: where to put the result | 668 | * @buf: where to put the result |
640 | * @count: maximum to send along | 669 | * @count: maximum to send along |
641 | * @ppos: where to start | 670 | * @ppos: where to start |
642 | * | 671 | * |
643 | * Returns number of bytes read or error code, as appropriate | 672 | * Returns number of bytes read or error code, as appropriate |
644 | */ | 673 | */ |
645 | static ssize_t smk_read_direct(struct file *filp, char __user *buf, | 674 | static ssize_t smk_read_direct(struct file *filp, char __user *buf, |
646 | size_t count, loff_t *ppos) | 675 | size_t count, loff_t *ppos) |
647 | { | 676 | { |
648 | char temp[80]; | 677 | char temp[80]; |
649 | ssize_t rc; | 678 | ssize_t rc; |
650 | 679 | ||
651 | if (*ppos != 0) | 680 | if (*ppos != 0) |
652 | return 0; | 681 | return 0; |
653 | 682 | ||
654 | sprintf(temp, "%d", smack_cipso_direct); | 683 | sprintf(temp, "%d", smack_cipso_direct); |
655 | rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp)); | 684 | rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp)); |
656 | 685 | ||
657 | return rc; | 686 | return rc; |
658 | } | 687 | } |
659 | 688 | ||
660 | /** | 689 | /** |
661 | * smk_write_direct - write() for /smack/direct | 690 | * smk_write_direct - write() for /smack/direct |
662 | * @filp: file pointer, not actually used | 691 | * @filp: file pointer, not actually used |
663 | * @buf: where to get the data from | 692 | * @buf: where to get the data from |
664 | * @count: bytes sent | 693 | * @count: bytes sent |
665 | * @ppos: where to start | 694 | * @ppos: where to start |
666 | * | 695 | * |
667 | * Returns number of bytes written or error code, as appropriate | 696 | * Returns number of bytes written or error code, as appropriate |
668 | */ | 697 | */ |
669 | static ssize_t smk_write_direct(struct file *file, const char __user *buf, | 698 | static ssize_t smk_write_direct(struct file *file, const char __user *buf, |
670 | size_t count, loff_t *ppos) | 699 | size_t count, loff_t *ppos) |
671 | { | 700 | { |
672 | char temp[80]; | 701 | char temp[80]; |
673 | int i; | 702 | int i; |
674 | 703 | ||
675 | if (!capable(CAP_MAC_ADMIN)) | 704 | if (!capable(CAP_MAC_ADMIN)) |
676 | return -EPERM; | 705 | return -EPERM; |
677 | 706 | ||
678 | if (count >= sizeof(temp) || count == 0) | 707 | if (count >= sizeof(temp) || count == 0) |
679 | return -EINVAL; | 708 | return -EINVAL; |
680 | 709 | ||
681 | if (copy_from_user(temp, buf, count) != 0) | 710 | if (copy_from_user(temp, buf, count) != 0) |
682 | return -EFAULT; | 711 | return -EFAULT; |
683 | 712 | ||
684 | temp[count] = '\0'; | 713 | temp[count] = '\0'; |
685 | 714 | ||
686 | if (sscanf(temp, "%d", &i) != 1) | 715 | if (sscanf(temp, "%d", &i) != 1) |
687 | return -EINVAL; | 716 | return -EINVAL; |
688 | 717 | ||
689 | smack_cipso_direct = i; | 718 | smack_cipso_direct = i; |
690 | 719 | ||
691 | return count; | 720 | return count; |
692 | } | 721 | } |
693 | 722 | ||
694 | static const struct file_operations smk_direct_ops = { | 723 | static const struct file_operations smk_direct_ops = { |
695 | .read = smk_read_direct, | 724 | .read = smk_read_direct, |
696 | .write = smk_write_direct, | 725 | .write = smk_write_direct, |
697 | }; | 726 | }; |
698 | 727 | ||
699 | /** | 728 | /** |
700 | * smk_read_ambient - read() for /smack/ambient | 729 | * smk_read_ambient - read() for /smack/ambient |
701 | * @filp: file pointer, not actually used | 730 | * @filp: file pointer, not actually used |
702 | * @buf: where to put the result | 731 | * @buf: where to put the result |
703 | * @cn: maximum to send along | 732 | * @cn: maximum to send along |
704 | * @ppos: where to start | 733 | * @ppos: where to start |
705 | * | 734 | * |
706 | * Returns number of bytes read or error code, as appropriate | 735 | * Returns number of bytes read or error code, as appropriate |
707 | */ | 736 | */ |
708 | static ssize_t smk_read_ambient(struct file *filp, char __user *buf, | 737 | static ssize_t smk_read_ambient(struct file *filp, char __user *buf, |
709 | size_t cn, loff_t *ppos) | 738 | size_t cn, loff_t *ppos) |
710 | { | 739 | { |
711 | ssize_t rc; | 740 | ssize_t rc; |
712 | char out[SMK_LABELLEN]; | ||
713 | int asize; | 741 | int asize; |
714 | 742 | ||
715 | if (*ppos != 0) | 743 | if (*ppos != 0) |
716 | return 0; | 744 | return 0; |
717 | /* | 745 | /* |
718 | * Being careful to avoid a problem in the case where | 746 | * Being careful to avoid a problem in the case where |
719 | * smack_net_ambient gets changed in midstream. | 747 | * smack_net_ambient gets changed in midstream. |
720 | * Since smack_net_ambient is always set with a value | ||
721 | * from the label list, including initially, and those | ||
722 | * never get freed, the worst case is that the pointer | ||
723 | * gets changed just after this strncpy, in which case | ||
724 | * the value passed up is incorrect. Locking around | ||
725 | * smack_net_ambient wouldn't be any better than this | ||
726 | * copy scheme as by the time the caller got to look | ||
727 | * at the ambient value it would have cleared the lock | ||
728 | * and been changed. | ||
729 | */ | 748 | */ |
730 | strncpy(out, smack_net_ambient, SMK_LABELLEN); | 749 | mutex_lock(&smack_ambient_lock); |
731 | asize = strlen(out) + 1; | ||
732 | 750 | ||
733 | if (cn < asize) | 751 | asize = strlen(smack_net_ambient) + 1; |
734 | return -EINVAL; | ||
735 | 752 | ||
736 | rc = simple_read_from_buffer(buf, cn, ppos, out, asize); | 753 | if (cn >= asize) |
754 | rc = simple_read_from_buffer(buf, cn, ppos, | ||
755 | smack_net_ambient, asize); | ||
756 | else | ||
757 | rc = -EINVAL; | ||
737 | 758 | ||
759 | mutex_unlock(&smack_ambient_lock); | ||
760 | |||
738 | return rc; | 761 | return rc; |
739 | } | 762 | } |
740 | 763 | ||
741 | /** | 764 | /** |
742 | * smk_write_ambient - write() for /smack/ambient | 765 | * smk_write_ambient - write() for /smack/ambient |
743 | * @filp: file pointer, not actually used | 766 | * @filp: file pointer, not actually used |
744 | * @buf: where to get the data from | 767 | * @buf: where to get the data from |
745 | * @count: bytes sent | 768 | * @count: bytes sent |
746 | * @ppos: where to start | 769 | * @ppos: where to start |
747 | * | 770 | * |
748 | * Returns number of bytes written or error code, as appropriate | 771 | * Returns number of bytes written or error code, as appropriate |
749 | */ | 772 | */ |
750 | static ssize_t smk_write_ambient(struct file *file, const char __user *buf, | 773 | static ssize_t smk_write_ambient(struct file *file, const char __user *buf, |
751 | size_t count, loff_t *ppos) | 774 | size_t count, loff_t *ppos) |
752 | { | 775 | { |
753 | char in[SMK_LABELLEN]; | 776 | char in[SMK_LABELLEN]; |
777 | char *oldambient; | ||
754 | char *smack; | 778 | char *smack; |
755 | 779 | ||
756 | if (!capable(CAP_MAC_ADMIN)) | 780 | if (!capable(CAP_MAC_ADMIN)) |
757 | return -EPERM; | 781 | return -EPERM; |
758 | 782 | ||
759 | if (count >= SMK_LABELLEN) | 783 | if (count >= SMK_LABELLEN) |
760 | return -EINVAL; | 784 | return -EINVAL; |
761 | 785 | ||
762 | if (copy_from_user(in, buf, count) != 0) | 786 | if (copy_from_user(in, buf, count) != 0) |
763 | return -EFAULT; | 787 | return -EFAULT; |
764 | 788 | ||
765 | smack = smk_import(in, count); | 789 | smack = smk_import(in, count); |
766 | if (smack == NULL) | 790 | if (smack == NULL) |
767 | return -EINVAL; | 791 | return -EINVAL; |
768 | 792 | ||
793 | mutex_lock(&smack_ambient_lock); | ||
794 | |||
795 | oldambient = smack_net_ambient; | ||
769 | smack_net_ambient = smack; | 796 | smack_net_ambient = smack; |
797 | smk_unlbl_ambient(oldambient); | ||
770 | 798 | ||
799 | mutex_unlock(&smack_ambient_lock); | ||
800 | |||
771 | return count; | 801 | return count; |
772 | } | 802 | } |
773 | 803 | ||
774 | static const struct file_operations smk_ambient_ops = { | 804 | static const struct file_operations smk_ambient_ops = { |
775 | .read = smk_read_ambient, | 805 | .read = smk_read_ambient, |
776 | .write = smk_write_ambient, | 806 | .write = smk_write_ambient, |
777 | }; | 807 | }; |
778 | 808 | ||
779 | struct option_names { | 809 | struct option_names { |
780 | int o_number; | 810 | int o_number; |
781 | char *o_name; | 811 | char *o_name; |
782 | char *o_alias; | 812 | char *o_alias; |
783 | }; | 813 | }; |
784 | 814 | ||
785 | static struct option_names netlbl_choices[] = { | 815 | static struct option_names netlbl_choices[] = { |
786 | { NETLBL_NLTYPE_RIPSO, | 816 | { NETLBL_NLTYPE_RIPSO, |
787 | NETLBL_NLTYPE_RIPSO_NAME, "ripso" }, | 817 | NETLBL_NLTYPE_RIPSO_NAME, "ripso" }, |
788 | { NETLBL_NLTYPE_CIPSOV4, | 818 | { NETLBL_NLTYPE_CIPSOV4, |
789 | NETLBL_NLTYPE_CIPSOV4_NAME, "cipsov4" }, | 819 | NETLBL_NLTYPE_CIPSOV4_NAME, "cipsov4" }, |
790 | { NETLBL_NLTYPE_CIPSOV4, | 820 | { NETLBL_NLTYPE_CIPSOV4, |
791 | NETLBL_NLTYPE_CIPSOV4_NAME, "cipso" }, | 821 | NETLBL_NLTYPE_CIPSOV4_NAME, "cipso" }, |
792 | { NETLBL_NLTYPE_CIPSOV6, | 822 | { NETLBL_NLTYPE_CIPSOV6, |
793 | NETLBL_NLTYPE_CIPSOV6_NAME, "cipsov6" }, | 823 | NETLBL_NLTYPE_CIPSOV6_NAME, "cipsov6" }, |
794 | { NETLBL_NLTYPE_UNLABELED, | 824 | { NETLBL_NLTYPE_UNLABELED, |
795 | NETLBL_NLTYPE_UNLABELED_NAME, "unlabeled" }, | 825 | NETLBL_NLTYPE_UNLABELED_NAME, "unlabeled" }, |
796 | }; | 826 | }; |
797 | 827 | ||
798 | /** | 828 | /** |
799 | * smk_read_nltype - read() for /smack/nltype | 829 | * smk_read_nltype - read() for /smack/nltype |
800 | * @filp: file pointer, not actually used | 830 | * @filp: file pointer, not actually used |
801 | * @buf: where to put the result | 831 | * @buf: where to put the result |
802 | * @count: maximum to send along | 832 | * @count: maximum to send along |
803 | * @ppos: where to start | 833 | * @ppos: where to start |
804 | * | 834 | * |
805 | * Returns number of bytes read or error code, as appropriate | 835 | * Returns number of bytes read or error code, as appropriate |
806 | */ | 836 | */ |
807 | static ssize_t smk_read_nltype(struct file *filp, char __user *buf, | 837 | static ssize_t smk_read_nltype(struct file *filp, char __user *buf, |
808 | size_t count, loff_t *ppos) | 838 | size_t count, loff_t *ppos) |
809 | { | 839 | { |
810 | char bound[40]; | 840 | char bound[40]; |
811 | ssize_t rc; | 841 | ssize_t rc; |
812 | int i; | 842 | int i; |
813 | 843 | ||
814 | if (count < SMK_LABELLEN) | 844 | if (count < SMK_LABELLEN) |
815 | return -EINVAL; | 845 | return -EINVAL; |
816 | 846 | ||
817 | if (*ppos != 0) | 847 | if (*ppos != 0) |
818 | return 0; | 848 | return 0; |
819 | 849 | ||
820 | sprintf(bound, "unknown"); | 850 | sprintf(bound, "unknown"); |
821 | 851 | ||
822 | for (i = 0; i < ARRAY_SIZE(netlbl_choices); i++) | 852 | for (i = 0; i < ARRAY_SIZE(netlbl_choices); i++) |
823 | if (smack_net_nltype == netlbl_choices[i].o_number) { | 853 | if (smack_net_nltype == netlbl_choices[i].o_number) { |
824 | sprintf(bound, "%s", netlbl_choices[i].o_name); | 854 | sprintf(bound, "%s", netlbl_choices[i].o_name); |
825 | break; | 855 | break; |
826 | } | 856 | } |
827 | 857 | ||
828 | rc = simple_read_from_buffer(buf, count, ppos, bound, strlen(bound)); | 858 | rc = simple_read_from_buffer(buf, count, ppos, bound, strlen(bound)); |
829 | 859 | ||
830 | return rc; | 860 | return rc; |
831 | } | 861 | } |
832 | 862 | ||
833 | /** | 863 | /** |
834 | * smk_write_nltype - write() for /smack/nltype | 864 | * smk_write_nltype - write() for /smack/nltype |
835 | * @filp: file pointer, not actually used | 865 | * @filp: file pointer, not actually used |
836 | * @buf: where to get the data from | 866 | * @buf: where to get the data from |
837 | * @count: bytes sent | 867 | * @count: bytes sent |
838 | * @ppos: where to start | 868 | * @ppos: where to start |
839 | * | 869 | * |
840 | * Returns number of bytes written or error code, as appropriate | 870 | * Returns number of bytes written or error code, as appropriate |
841 | */ | 871 | */ |
842 | static ssize_t smk_write_nltype(struct file *file, const char __user *buf, | 872 | static ssize_t smk_write_nltype(struct file *file, const char __user *buf, |
843 | size_t count, loff_t *ppos) | 873 | size_t count, loff_t *ppos) |
844 | { | 874 | { |
845 | char bound[40]; | 875 | char bound[40]; |
846 | char *cp; | 876 | char *cp; |
847 | int i; | 877 | int i; |
848 | 878 | ||
849 | if (!capable(CAP_MAC_ADMIN)) | 879 | if (!capable(CAP_MAC_ADMIN)) |
850 | return -EPERM; | 880 | return -EPERM; |
851 | 881 | ||
852 | if (count >= 40) | 882 | if (count >= 40) |
853 | return -EINVAL; | 883 | return -EINVAL; |
854 | 884 | ||
855 | if (copy_from_user(bound, buf, count) != 0) | 885 | if (copy_from_user(bound, buf, count) != 0) |
856 | return -EFAULT; | 886 | return -EFAULT; |
857 | 887 | ||
858 | bound[count] = '\0'; | 888 | bound[count] = '\0'; |
859 | cp = strchr(bound, ' '); | 889 | cp = strchr(bound, ' '); |
860 | if (cp != NULL) | 890 | if (cp != NULL) |
861 | *cp = '\0'; | 891 | *cp = '\0'; |
862 | cp = strchr(bound, '\n'); | 892 | cp = strchr(bound, '\n'); |
863 | if (cp != NULL) | 893 | if (cp != NULL) |
864 | *cp = '\0'; | 894 | *cp = '\0'; |
865 | 895 | ||
866 | for (i = 0; i < ARRAY_SIZE(netlbl_choices); i++) | 896 | for (i = 0; i < ARRAY_SIZE(netlbl_choices); i++) |
867 | if (strcmp(bound, netlbl_choices[i].o_name) == 0 || | 897 | if (strcmp(bound, netlbl_choices[i].o_name) == 0 || |
868 | strcmp(bound, netlbl_choices[i].o_alias) == 0) { | 898 | strcmp(bound, netlbl_choices[i].o_alias) == 0) { |
869 | smack_net_nltype = netlbl_choices[i].o_number; | 899 | smack_net_nltype = netlbl_choices[i].o_number; |
870 | return count; | 900 | return count; |
871 | } | 901 | } |
872 | /* | 902 | /* |
873 | * Not a valid choice. | 903 | * Not a valid choice. |
874 | */ | 904 | */ |
875 | return -EINVAL; | 905 | return -EINVAL; |
876 | } | 906 | } |
877 | 907 | ||
878 | static const struct file_operations smk_nltype_ops = { | 908 | static const struct file_operations smk_nltype_ops = { |
879 | .read = smk_read_nltype, | 909 | .read = smk_read_nltype, |
880 | .write = smk_write_nltype, | 910 | .write = smk_write_nltype, |
881 | }; | 911 | }; |
882 | 912 | ||
883 | /** | 913 | /** |
884 | * smk_fill_super - fill the /smackfs superblock | 914 | * smk_fill_super - fill the /smackfs superblock |
885 | * @sb: the empty superblock | 915 | * @sb: the empty superblock |
886 | * @data: unused | 916 | * @data: unused |
887 | * @silent: unused | 917 | * @silent: unused |
888 | * | 918 | * |
889 | * Fill in the well known entries for /smack | 919 | * Fill in the well known entries for /smack |
890 | * | 920 | * |
891 | * Returns 0 on success, an error code on failure | 921 | * Returns 0 on success, an error code on failure |
892 | */ | 922 | */ |
893 | static int smk_fill_super(struct super_block *sb, void *data, int silent) | 923 | static int smk_fill_super(struct super_block *sb, void *data, int silent) |
894 | { | 924 | { |
895 | int rc; | 925 | int rc; |
896 | struct inode *root_inode; | 926 | struct inode *root_inode; |
897 | 927 | ||
898 | static struct tree_descr smack_files[] = { | 928 | static struct tree_descr smack_files[] = { |
899 | [SMK_LOAD] = | 929 | [SMK_LOAD] = |
900 | {"load", &smk_load_ops, S_IRUGO|S_IWUSR}, | 930 | {"load", &smk_load_ops, S_IRUGO|S_IWUSR}, |
901 | [SMK_CIPSO] = | 931 | [SMK_CIPSO] = |
902 | {"cipso", &smk_cipso_ops, S_IRUGO|S_IWUSR}, | 932 | {"cipso", &smk_cipso_ops, S_IRUGO|S_IWUSR}, |
903 | [SMK_DOI] = | 933 | [SMK_DOI] = |
904 | {"doi", &smk_doi_ops, S_IRUGO|S_IWUSR}, | 934 | {"doi", &smk_doi_ops, S_IRUGO|S_IWUSR}, |
905 | [SMK_DIRECT] = | 935 | [SMK_DIRECT] = |
906 | {"direct", &smk_direct_ops, S_IRUGO|S_IWUSR}, | 936 | {"direct", &smk_direct_ops, S_IRUGO|S_IWUSR}, |
907 | [SMK_AMBIENT] = | 937 | [SMK_AMBIENT] = |
908 | {"ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR}, | 938 | {"ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR}, |
909 | [SMK_NLTYPE] = | 939 | [SMK_NLTYPE] = |
910 | {"nltype", &smk_nltype_ops, S_IRUGO|S_IWUSR}, | 940 | {"nltype", &smk_nltype_ops, S_IRUGO|S_IWUSR}, |
911 | /* last one */ {""} | 941 | /* last one */ {""} |
912 | }; | 942 | }; |
913 | 943 | ||
914 | rc = simple_fill_super(sb, SMACK_MAGIC, smack_files); | 944 | rc = simple_fill_super(sb, SMACK_MAGIC, smack_files); |
915 | if (rc != 0) { | 945 | if (rc != 0) { |
916 | printk(KERN_ERR "%s failed %d while creating inodes\n", | 946 | printk(KERN_ERR "%s failed %d while creating inodes\n", |
917 | __func__, rc); | 947 | __func__, rc); |
918 | return rc; | 948 | return rc; |
919 | } | 949 | } |
920 | 950 | ||
921 | root_inode = sb->s_root->d_inode; | 951 | root_inode = sb->s_root->d_inode; |
922 | root_inode->i_security = new_inode_smack(smack_known_floor.smk_known); | 952 | root_inode->i_security = new_inode_smack(smack_known_floor.smk_known); |
923 | 953 | ||
924 | return 0; | 954 | return 0; |
925 | } | 955 | } |
926 | 956 | ||
927 | /** | 957 | /** |
928 | * smk_get_sb - get the smackfs superblock | 958 | * smk_get_sb - get the smackfs superblock |
929 | * @fs_type: passed along without comment | 959 | * @fs_type: passed along without comment |
930 | * @flags: passed along without comment | 960 | * @flags: passed along without comment |
931 | * @dev_name: passed along without comment | 961 | * @dev_name: passed along without comment |
932 | * @data: passed along without comment | 962 | * @data: passed along without comment |
933 | * @mnt: passed along without comment | 963 | * @mnt: passed along without comment |
934 | * | 964 | * |
935 | * Just passes everything along. | 965 | * Just passes everything along. |
936 | * | 966 | * |
937 | * Returns what the lower level code does. | 967 | * Returns what the lower level code does. |
938 | */ | 968 | */ |
939 | static int smk_get_sb(struct file_system_type *fs_type, | 969 | static int smk_get_sb(struct file_system_type *fs_type, |
940 | int flags, const char *dev_name, void *data, | 970 | int flags, const char *dev_name, void *data, |
941 | struct vfsmount *mnt) | 971 | struct vfsmount *mnt) |
942 | { | 972 | { |
943 | return get_sb_single(fs_type, flags, data, smk_fill_super, mnt); | 973 | return get_sb_single(fs_type, flags, data, smk_fill_super, mnt); |
944 | } | 974 | } |
945 | 975 | ||
946 | static struct file_system_type smk_fs_type = { | 976 | static struct file_system_type smk_fs_type = { |
947 | .name = "smackfs", | 977 | .name = "smackfs", |
948 | .get_sb = smk_get_sb, | 978 | .get_sb = smk_get_sb, |
949 | .kill_sb = kill_litter_super, | 979 | .kill_sb = kill_litter_super, |
950 | }; | 980 | }; |
951 | 981 | ||
952 | static struct vfsmount *smackfs_mount; | 982 | static struct vfsmount *smackfs_mount; |
953 | 983 | ||
954 | /** | 984 | /** |
955 | * init_smk_fs - get the smackfs superblock | 985 | * init_smk_fs - get the smackfs superblock |
956 | * | 986 | * |
957 | * register the smackfs | 987 | * register the smackfs |
958 | * | 988 | * |
959 | * Returns 0 unless the registration fails. | 989 | * Returns 0 unless the registration fails. |
960 | */ | 990 | */ |
961 | static int __init init_smk_fs(void) | 991 | static int __init init_smk_fs(void) |
962 | { | 992 | { |
963 | int err; | 993 | int err; |
964 | 994 | ||
965 | err = register_filesystem(&smk_fs_type); | 995 | err = register_filesystem(&smk_fs_type); |
966 | if (!err) { | 996 | if (!err) { |
967 | smackfs_mount = kern_mount(&smk_fs_type); | 997 | smackfs_mount = kern_mount(&smk_fs_type); |
968 | if (IS_ERR(smackfs_mount)) { | 998 | if (IS_ERR(smackfs_mount)) { |
969 | printk(KERN_ERR "smackfs: could not mount!\n"); | 999 | printk(KERN_ERR "smackfs: could not mount!\n"); |
970 | err = PTR_ERR(smackfs_mount); | 1000 | err = PTR_ERR(smackfs_mount); |
971 | smackfs_mount = NULL; | 1001 | smackfs_mount = NULL; |