blob: 29b760d6b746ed99d45eeee5ced2b77ae2883030 [file] [log] [blame]
Casey Schauflere114e472008-02-04 22:29:50 -08001/*
2 * Copyright (C) 2007 Casey Schaufler <casey@schaufler-ca.com>
3 *
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
6 * the Free Software Foundation, version 2.
7 *
8 * Authors:
9 * Casey Schaufler <casey@schaufler-ca.com>
10 * Ahmed S. Darwish <darwish.07@gmail.com>
11 *
12 * Special thanks to the authors of selinuxfs.
13 *
14 * Karl MacMillan <kmacmillan@tresys.com>
15 * James Morris <jmorris@redhat.com>
16 *
17 */
18
19#include <linux/kernel.h>
20#include <linux/vmalloc.h>
21#include <linux/security.h>
22#include <linux/mutex.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090023#include <linux/slab.h>
Casey Schaufler6d3dc072008-12-31 12:54:12 -050024#include <net/net_namespace.h>
Casey Schauflere114e472008-02-04 22:29:50 -080025#include <net/cipso_ipv4.h>
26#include <linux/seq_file.h>
27#include <linux/ctype.h>
Casey Schaufler4bc87e62008-02-15 15:24:25 -080028#include <linux/audit.h>
Casey Schauflere114e472008-02-04 22:29:50 -080029#include "smack.h"
30
31/*
32 * smackfs pseudo filesystem.
33 */
34
35enum smk_inos {
36 SMK_ROOT_INO = 2,
37 SMK_LOAD = 3, /* load policy */
38 SMK_CIPSO = 4, /* load label -> CIPSO mapping */
39 SMK_DOI = 5, /* CIPSO DOI */
40 SMK_DIRECT = 6, /* CIPSO level indicating direct label */
41 SMK_AMBIENT = 7, /* internet ambient label */
Casey Schaufler6d3dc072008-12-31 12:54:12 -050042 SMK_NETLBLADDR = 8, /* single label hosts */
Casey Schaufler15446232008-07-30 15:37:11 -070043 SMK_ONLYCAP = 9, /* the only "capable" label */
Etienne Bassetecfcc532009-04-08 20:40:06 +020044 SMK_LOGGING = 10, /* logging */
Casey Schaufler7898e1f2011-01-17 08:05:27 -080045 SMK_LOAD_SELF = 11, /* task specific rules */
Jarkko Sakkinen828716c2011-09-08 10:12:01 +030046 SMK_ACCESSES = 12, /* access policy */
Casey Schauflerf7112e62012-05-06 15:22:02 -070047 SMK_MAPPED = 13, /* CIPSO level indicating mapped label */
48 SMK_LOAD2 = 14, /* load policy with long labels */
49 SMK_LOAD_SELF2 = 15, /* load task specific rules with long labels */
50 SMK_ACCESS2 = 16, /* make an access check with long labels */
51 SMK_CIPSO2 = 17, /* load long label -> CIPSO mapping */
Casey Schauflere114e472008-02-04 22:29:50 -080052};
53
54/*
55 * List locks
56 */
57static DEFINE_MUTEX(smack_list_lock);
58static DEFINE_MUTEX(smack_cipso_lock);
Casey Schaufler4bc87e62008-02-15 15:24:25 -080059static DEFINE_MUTEX(smack_ambient_lock);
Casey Schaufler6d3dc072008-12-31 12:54:12 -050060static DEFINE_MUTEX(smk_netlbladdr_lock);
Casey Schauflere114e472008-02-04 22:29:50 -080061
62/*
63 * This is the "ambient" label for network traffic.
64 * If it isn't somehow marked, use this.
65 * It can be reset via smackfs/ambient
66 */
Casey Schauflerf7112e62012-05-06 15:22:02 -070067char *smack_net_ambient;
Casey Schauflere114e472008-02-04 22:29:50 -080068
69/*
Casey Schauflere114e472008-02-04 22:29:50 -080070 * This is the level in a CIPSO header that indicates a
71 * smack label is contained directly in the category set.
72 * It can be reset via smackfs/direct
73 */
74int smack_cipso_direct = SMACK_CIPSO_DIRECT_DEFAULT;
75
Casey Schaufler15446232008-07-30 15:37:11 -070076/*
Casey Schauflerf7112e62012-05-06 15:22:02 -070077 * This is the level in a CIPSO header that indicates a
78 * secid is contained directly in the category set.
79 * It can be reset via smackfs/mapped
80 */
81int smack_cipso_mapped = SMACK_CIPSO_MAPPED_DEFAULT;
82
83/*
Casey Schaufler15446232008-07-30 15:37:11 -070084 * Unless a process is running with this label even
85 * having CAP_MAC_OVERRIDE isn't enough to grant
86 * privilege to violate MAC policy. If no label is
87 * designated (the NULL case) capabilities apply to
88 * everyone. It is expected that the hat (^) label
89 * will be used if any label is used.
90 */
91char *smack_onlycap;
92
Casey Schaufler6d3dc072008-12-31 12:54:12 -050093/*
94 * Certain IP addresses may be designated as single label hosts.
95 * Packets are sent there unlabeled, but only from tasks that
96 * can write to the specified label.
97 */
Etienne Basset7198e2e2009-03-24 20:53:24 +010098
99LIST_HEAD(smk_netlbladdr_list);
Casey Schaufler272cd7a2011-09-20 12:24:36 -0700100
101/*
102 * Rule lists are maintained for each label.
Casey Schauflerf7112e62012-05-06 15:22:02 -0700103 * This master list is just for reading /smack/load and /smack/load2.
Casey Schaufler272cd7a2011-09-20 12:24:36 -0700104 */
105struct smack_master_list {
106 struct list_head list;
107 struct smack_rule *smk_rule;
108};
109
Etienne Basset7198e2e2009-03-24 20:53:24 +0100110LIST_HEAD(smack_rule_list);
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500111
Casey Schauflere114e472008-02-04 22:29:50 -0800112static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT;
Casey Schauflere114e472008-02-04 22:29:50 -0800113
Etienne Basset43031542009-03-27 17:11:01 -0400114const char *smack_cipso_option = SMACK_CIPSO_OPTION;
115
Casey Schauflere114e472008-02-04 22:29:50 -0800116/*
Casey Schauflere114e472008-02-04 22:29:50 -0800117 * Values for parsing cipso rules
118 * SMK_DIGITLEN: Length of a digit field in a rule.
Ahmed S. Darwishb500ce82008-03-13 12:32:34 -0700119 * SMK_CIPSOMIN: Minimum possible cipso rule length.
120 * SMK_CIPSOMAX: Maximum possible cipso rule length.
Casey Schauflere114e472008-02-04 22:29:50 -0800121 */
122#define SMK_DIGITLEN 4
Ahmed S. Darwishb500ce82008-03-13 12:32:34 -0700123#define SMK_CIPSOMIN (SMK_LABELLEN + 2 * SMK_DIGITLEN)
124#define SMK_CIPSOMAX (SMK_CIPSOMIN + SMACK_CIPSO_MAXCATNUM * SMK_DIGITLEN)
125
126/*
127 * Values for parsing MAC rules
128 * SMK_ACCESS: Maximum possible combination of access permissions
129 * SMK_ACCESSLEN: Maximum length for a rule access field
130 * SMK_LOADLEN: Smack rule length
131 */
Jarkko Sakkinen5c6d1122010-12-07 13:34:01 +0200132#define SMK_OACCESS "rwxa"
133#define SMK_ACCESS "rwxat"
134#define SMK_OACCESSLEN (sizeof(SMK_OACCESS) - 1)
135#define SMK_ACCESSLEN (sizeof(SMK_ACCESS) - 1)
136#define SMK_OLOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_OACCESSLEN)
137#define SMK_LOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_ACCESSLEN)
Ahmed S. Darwishb500ce82008-03-13 12:32:34 -0700138
Casey Schauflerf7112e62012-05-06 15:22:02 -0700139/*
140 * Stricly for CIPSO level manipulation.
141 * Set the category bit number in a smack label sized buffer.
142 */
143static inline void smack_catset_bit(unsigned int cat, char *catsetp)
144{
145 if (cat == 0 || cat > (SMK_CIPSOLEN * 8))
146 return;
147
148 catsetp[(cat - 1) / 8] |= 0x80 >> ((cat - 1) % 8);
149}
150
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500151/**
152 * smk_netlabel_audit_set - fill a netlbl_audit struct
153 * @nap: structure to fill
154 */
155static void smk_netlabel_audit_set(struct netlbl_audit *nap)
156{
157 nap->loginuid = audit_get_loginuid(current);
158 nap->sessionid = audit_get_sessionid(current);
Casey Schaufler676dac42010-12-02 06:43:39 -0800159 nap->secid = smack_to_secid(smk_of_current());
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500160}
161
162/*
Casey Schauflerf7112e62012-05-06 15:22:02 -0700163 * Value for parsing single label host rules
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500164 * "1.2.3.4 X"
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500165 */
166#define SMK_NETLBLADDRMIN 9
Casey Schauflere114e472008-02-04 22:29:50 -0800167
Casey Schauflere114e472008-02-04 22:29:50 -0800168/**
169 * smk_set_access - add a rule to the rule list
170 * @srp: the new rule to add
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800171 * @rule_list: the list of rules
172 * @rule_lock: the rule list lock
Casey Schauflere114e472008-02-04 22:29:50 -0800173 *
174 * Looks through the current subject/object/access list for
175 * the subject/object pair and replaces the access that was
176 * there. If the pair isn't found add it with the specified
177 * access.
Sergio Luis81ea7142008-12-22 01:16:15 -0300178 *
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800179 * Returns 1 if a rule was found to exist already, 0 if it is new
Sergio Luis81ea7142008-12-22 01:16:15 -0300180 * Returns 0 if nothing goes wrong or -ENOMEM if it fails
181 * during the allocation of the new pair to add.
Casey Schauflere114e472008-02-04 22:29:50 -0800182 */
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800183static int smk_set_access(struct smack_rule *srp, struct list_head *rule_list,
184 struct mutex *rule_lock)
Casey Schauflere114e472008-02-04 22:29:50 -0800185{
Etienne Basset7198e2e2009-03-24 20:53:24 +0100186 struct smack_rule *sp;
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800187 int found = 0;
Casey Schauflere114e472008-02-04 22:29:50 -0800188
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800189 mutex_lock(rule_lock);
190
Casey Schaufler272cd7a2011-09-20 12:24:36 -0700191 /*
192 * Because the object label is less likely to match
193 * than the subject label check it first
194 */
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800195 list_for_each_entry_rcu(sp, rule_list, list) {
Casey Schaufler272cd7a2011-09-20 12:24:36 -0700196 if (sp->smk_object == srp->smk_object &&
197 sp->smk_subject == srp->smk_subject) {
Etienne Basset7198e2e2009-03-24 20:53:24 +0100198 found = 1;
199 sp->smk_access = srp->smk_access;
Casey Schauflere114e472008-02-04 22:29:50 -0800200 break;
201 }
Casey Schauflere114e472008-02-04 22:29:50 -0800202 }
Etienne Basset7198e2e2009-03-24 20:53:24 +0100203 if (found == 0)
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800204 list_add_rcu(&srp->list, rule_list);
Casey Schauflere114e472008-02-04 22:29:50 -0800205
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800206 mutex_unlock(rule_lock);
Casey Schauflere114e472008-02-04 22:29:50 -0800207
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800208 return found;
Casey Schauflere114e472008-02-04 22:29:50 -0800209}
210
211/**
Casey Schauflerf7112e62012-05-06 15:22:02 -0700212 * smk_fill_rule - Fill Smack rule from strings
213 * @subject: subject label string
214 * @object: object label string
215 * @access: access string
Jarkko Sakkinen0e94ae12011-10-18 21:21:36 +0300216 * @rule: Smack rule
217 * @import: if non-zero, import labels
Casey Schaufler35187212012-06-18 19:01:36 -0700218 * @len: label length limit
Casey Schauflerf7112e62012-05-06 15:22:02 -0700219 *
220 * Returns 0 on success, -1 on failure
Jarkko Sakkinen828716c2011-09-08 10:12:01 +0300221 */
Casey Schauflerf7112e62012-05-06 15:22:02 -0700222static int smk_fill_rule(const char *subject, const char *object,
223 const char *access, struct smack_rule *rule,
Casey Schaufler35187212012-06-18 19:01:36 -0700224 int import, int len)
Jarkko Sakkinen828716c2011-09-08 10:12:01 +0300225{
Casey Schauflerf7112e62012-05-06 15:22:02 -0700226 const char *cp;
Jarkko Sakkinen0e94ae12011-10-18 21:21:36 +0300227 struct smack_known *skp;
Jarkko Sakkinen828716c2011-09-08 10:12:01 +0300228
Jarkko Sakkinen0e94ae12011-10-18 21:21:36 +0300229 if (import) {
Casey Schaufler35187212012-06-18 19:01:36 -0700230 rule->smk_subject = smk_import(subject, len);
Jarkko Sakkinen0e94ae12011-10-18 21:21:36 +0300231 if (rule->smk_subject == NULL)
232 return -1;
233
Casey Schaufler35187212012-06-18 19:01:36 -0700234 rule->smk_object = smk_import(object, len);
Jarkko Sakkinen0e94ae12011-10-18 21:21:36 +0300235 if (rule->smk_object == NULL)
236 return -1;
237 } else {
Casey Schaufler35187212012-06-18 19:01:36 -0700238 cp = smk_parse_smack(subject, len);
Casey Schauflerf7112e62012-05-06 15:22:02 -0700239 if (cp == NULL)
240 return -1;
241 skp = smk_find_entry(cp);
242 kfree(cp);
Jarkko Sakkinen0e94ae12011-10-18 21:21:36 +0300243 if (skp == NULL)
244 return -1;
245 rule->smk_subject = skp->smk_known;
246
Casey Schaufler35187212012-06-18 19:01:36 -0700247 cp = smk_parse_smack(object, len);
Casey Schauflerf7112e62012-05-06 15:22:02 -0700248 if (cp == NULL)
249 return -1;
250 skp = smk_find_entry(cp);
251 kfree(cp);
Jarkko Sakkinen0e94ae12011-10-18 21:21:36 +0300252 if (skp == NULL)
253 return -1;
254 rule->smk_object = skp->smk_known;
255 }
Jarkko Sakkinen828716c2011-09-08 10:12:01 +0300256
257 rule->smk_access = 0;
258
Casey Schaufler35187212012-06-18 19:01:36 -0700259 for (cp = access; *cp != '\0'; cp++) {
Casey Schauflerf7112e62012-05-06 15:22:02 -0700260 switch (*cp) {
261 case '-':
262 break;
263 case 'r':
264 case 'R':
265 rule->smk_access |= MAY_READ;
266 break;
267 case 'w':
268 case 'W':
269 rule->smk_access |= MAY_WRITE;
270 break;
271 case 'x':
272 case 'X':
273 rule->smk_access |= MAY_EXEC;
274 break;
275 case 'a':
276 case 'A':
277 rule->smk_access |= MAY_APPEND;
278 break;
279 case 't':
280 case 'T':
281 rule->smk_access |= MAY_TRANSMUTE;
282 break;
283 default:
Casey Schaufler35187212012-06-18 19:01:36 -0700284 return 0;
Casey Schauflerf7112e62012-05-06 15:22:02 -0700285 }
Jarkko Sakkinen828716c2011-09-08 10:12:01 +0300286 }
287
Casey Schaufler35187212012-06-18 19:01:36 -0700288 return 0;
Jarkko Sakkinen828716c2011-09-08 10:12:01 +0300289}
290
291/**
Casey Schauflerf7112e62012-05-06 15:22:02 -0700292 * smk_parse_rule - parse Smack rule from load string
293 * @data: string to be parsed whose size is SMK_LOADLEN
294 * @rule: Smack rule
295 * @import: if non-zero, import labels
296 *
297 * Returns 0 on success, -1 on errors.
298 */
299static int smk_parse_rule(const char *data, struct smack_rule *rule, int import)
300{
301 int rc;
302
303 rc = smk_fill_rule(data, data + SMK_LABELLEN,
Casey Schaufler35187212012-06-18 19:01:36 -0700304 data + SMK_LABELLEN + SMK_LABELLEN, rule, import,
305 SMK_LABELLEN);
Casey Schauflerf7112e62012-05-06 15:22:02 -0700306 return rc;
307}
308
309/**
310 * smk_parse_long_rule - parse Smack rule from rule string
311 * @data: string to be parsed, null terminated
312 * @rule: Smack rule
313 * @import: if non-zero, import labels
314 *
315 * Returns 0 on success, -1 on failure
316 */
317static int smk_parse_long_rule(const char *data, struct smack_rule *rule,
318 int import)
319{
320 char *subject;
321 char *object;
322 char *access;
323 int datalen;
324 int rc = -1;
325
326 /*
327 * This is probably inefficient, but safe.
328 */
329 datalen = strlen(data);
330 subject = kzalloc(datalen, GFP_KERNEL);
331 if (subject == NULL)
332 return -1;
333 object = kzalloc(datalen, GFP_KERNEL);
334 if (object == NULL)
335 goto free_out_s;
336 access = kzalloc(datalen, GFP_KERNEL);
337 if (access == NULL)
338 goto free_out_o;
339
340 if (sscanf(data, "%s %s %s", subject, object, access) == 3)
Casey Schaufler35187212012-06-18 19:01:36 -0700341 rc = smk_fill_rule(subject, object, access, rule, import, 0);
Casey Schauflerf7112e62012-05-06 15:22:02 -0700342
343 kfree(access);
344free_out_o:
345 kfree(object);
346free_out_s:
347 kfree(subject);
348 return rc;
349}
350
351#define SMK_FIXED24_FMT 0 /* Fixed 24byte label format */
352#define SMK_LONG_FMT 1 /* Variable long label format */
353/**
354 * smk_write_rules_list - write() for any /smack rule file
Randy Dunlap251a2a92009-02-18 11:42:33 -0800355 * @file: file pointer, not actually used
Casey Schauflere114e472008-02-04 22:29:50 -0800356 * @buf: where to get the data from
357 * @count: bytes sent
358 * @ppos: where to start - must be 0
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800359 * @rule_list: the list of rules to write to
360 * @rule_lock: lock for the rule list
Casey Schauflerf7112e62012-05-06 15:22:02 -0700361 * @format: /smack/load or /smack/load2 format.
Casey Schauflere114e472008-02-04 22:29:50 -0800362 *
363 * Get one smack access rule from above.
Casey Schauflerf7112e62012-05-06 15:22:02 -0700364 * The format for SMK_LONG_FMT is:
365 * "subject<whitespace>object<whitespace>access[<whitespace>...]"
366 * The format for SMK_FIXED24_FMT is exactly:
367 * "subject object rwxat"
Casey Schauflere114e472008-02-04 22:29:50 -0800368 */
Casey Schauflerf7112e62012-05-06 15:22:02 -0700369static ssize_t smk_write_rules_list(struct file *file, const char __user *buf,
370 size_t count, loff_t *ppos,
371 struct list_head *rule_list,
372 struct mutex *rule_lock, int format)
Casey Schauflere114e472008-02-04 22:29:50 -0800373{
Casey Schaufler272cd7a2011-09-20 12:24:36 -0700374 struct smack_master_list *smlp;
375 struct smack_known *skp;
Etienne Basset7198e2e2009-03-24 20:53:24 +0100376 struct smack_rule *rule;
Casey Schauflere114e472008-02-04 22:29:50 -0800377 char *data;
Casey Schauflerf7112e62012-05-06 15:22:02 -0700378 int datalen;
Casey Schauflere114e472008-02-04 22:29:50 -0800379 int rc = -EINVAL;
Casey Schaufler272cd7a2011-09-20 12:24:36 -0700380 int load = 0;
Casey Schauflere114e472008-02-04 22:29:50 -0800381
382 /*
Casey Schauflere114e472008-02-04 22:29:50 -0800383 * No partial writes.
384 * Enough data must be present.
385 */
Jarkko Sakkinen5c6d1122010-12-07 13:34:01 +0200386 if (*ppos != 0)
387 return -EINVAL;
Casey Schauflere114e472008-02-04 22:29:50 -0800388
Casey Schauflerf7112e62012-05-06 15:22:02 -0700389 if (format == SMK_FIXED24_FMT) {
390 /*
391 * Minor hack for backward compatibility
392 */
393 if (count != SMK_OLOADLEN && count != SMK_LOADLEN)
394 return -EINVAL;
395 datalen = SMK_LOADLEN;
396 } else
397 datalen = count + 1;
398
399 data = kzalloc(datalen, GFP_KERNEL);
Casey Schauflere114e472008-02-04 22:29:50 -0800400 if (data == NULL)
401 return -ENOMEM;
402
403 if (copy_from_user(data, buf, count) != 0) {
404 rc = -EFAULT;
405 goto out;
406 }
407
Etienne Basset7198e2e2009-03-24 20:53:24 +0100408 rule = kzalloc(sizeof(*rule), GFP_KERNEL);
409 if (rule == NULL) {
410 rc = -ENOMEM;
Casey Schauflere114e472008-02-04 22:29:50 -0800411 goto out;
Etienne Basset7198e2e2009-03-24 20:53:24 +0100412 }
Casey Schauflere114e472008-02-04 22:29:50 -0800413
Casey Schauflerf7112e62012-05-06 15:22:02 -0700414 if (format == SMK_LONG_FMT) {
415 /*
416 * Be sure the data string is terminated.
417 */
418 data[count] = '\0';
419 if (smk_parse_long_rule(data, rule, 1))
420 goto out_free_rule;
421 } else {
422 /*
423 * More on the minor hack for backward compatibility
424 */
425 if (count == (SMK_OLOADLEN))
426 data[SMK_OLOADLEN] = '-';
427 if (smk_parse_rule(data, rule, 1))
428 goto out_free_rule;
429 }
430
Casey Schauflere114e472008-02-04 22:29:50 -0800431
Casey Schaufler272cd7a2011-09-20 12:24:36 -0700432 if (rule_list == NULL) {
433 load = 1;
434 skp = smk_find_entry(rule->smk_subject);
435 rule_list = &skp->smk_rules;
436 rule_lock = &skp->smk_rules_lock;
437 }
438
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800439 rc = count;
440 /*
Casey Schauflerf7112e62012-05-06 15:22:02 -0700441 * If this is a global as opposed to self and a new rule
Casey Schaufler40809562011-11-10 15:02:22 -0800442 * it needs to get added for reporting.
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800443 * smk_set_access returns true if there was already a rule
444 * for the subject/object pair, and false if it was new.
445 */
Casey Schauflerf7112e62012-05-06 15:22:02 -0700446 if (!smk_set_access(rule, rule_list, rule_lock)) {
447 if (load) {
448 smlp = kzalloc(sizeof(*smlp), GFP_KERNEL);
449 if (smlp != NULL) {
450 smlp->smk_rule = rule;
451 list_add_rcu(&smlp->list, &smack_rule_list);
452 } else
453 rc = -ENOMEM;
454 }
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800455 goto out;
Casey Schaufler272cd7a2011-09-20 12:24:36 -0700456 }
Casey Schauflere114e472008-02-04 22:29:50 -0800457
Etienne Basset7198e2e2009-03-24 20:53:24 +0100458out_free_rule:
459 kfree(rule);
Casey Schauflere114e472008-02-04 22:29:50 -0800460out:
461 kfree(data);
462 return rc;
463}
464
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800465/*
Casey Schaufler40809562011-11-10 15:02:22 -0800466 * Core logic for smackfs seq list operations.
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800467 */
468
Casey Schaufler40809562011-11-10 15:02:22 -0800469static void *smk_seq_start(struct seq_file *s, loff_t *pos,
470 struct list_head *head)
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800471{
Casey Schaufler272cd7a2011-09-20 12:24:36 -0700472 struct list_head *list;
473
474 /*
475 * This is 0 the first time through.
476 */
477 if (s->index == 0)
Casey Schaufler40809562011-11-10 15:02:22 -0800478 s->private = head;
Casey Schaufler272cd7a2011-09-20 12:24:36 -0700479
480 if (s->private == NULL)
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800481 return NULL;
Casey Schaufler272cd7a2011-09-20 12:24:36 -0700482
483 list = s->private;
484 if (list_empty(list))
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800485 return NULL;
Casey Schaufler272cd7a2011-09-20 12:24:36 -0700486
487 if (s->index == 0)
488 return list->next;
489 return list;
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800490}
491
Casey Schaufler40809562011-11-10 15:02:22 -0800492static void *smk_seq_next(struct seq_file *s, void *v, loff_t *pos,
493 struct list_head *head)
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800494{
495 struct list_head *list = v;
496
Casey Schaufler40809562011-11-10 15:02:22 -0800497 if (list_is_last(list, head)) {
Casey Schaufler272cd7a2011-09-20 12:24:36 -0700498 s->private = NULL;
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800499 return NULL;
500 }
Casey Schaufler272cd7a2011-09-20 12:24:36 -0700501 s->private = list->next;
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800502 return list->next;
503}
504
Casey Schaufler40809562011-11-10 15:02:22 -0800505static void smk_seq_stop(struct seq_file *s, void *v)
506{
507 /* No-op */
508}
509
Casey Schauflerf7112e62012-05-06 15:22:02 -0700510static void smk_rule_show(struct seq_file *s, struct smack_rule *srp, int max)
Casey Schaufler40809562011-11-10 15:02:22 -0800511{
Casey Schauflerf7112e62012-05-06 15:22:02 -0700512 /*
513 * Don't show any rules with label names too long for
514 * interface file (/smack/load or /smack/load2)
515 * because you should expect to be able to write
516 * anything you read back.
517 */
518 if (strlen(srp->smk_subject) >= max || strlen(srp->smk_object) >= max)
519 return;
Casey Schaufler40809562011-11-10 15:02:22 -0800520
Casey Schauflerf7112e62012-05-06 15:22:02 -0700521 seq_printf(s, "%s %s", srp->smk_subject, srp->smk_object);
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800522
523 seq_putc(s, ' ');
524
525 if (srp->smk_access & MAY_READ)
526 seq_putc(s, 'r');
527 if (srp->smk_access & MAY_WRITE)
528 seq_putc(s, 'w');
529 if (srp->smk_access & MAY_EXEC)
530 seq_putc(s, 'x');
531 if (srp->smk_access & MAY_APPEND)
532 seq_putc(s, 'a');
533 if (srp->smk_access & MAY_TRANSMUTE)
534 seq_putc(s, 't');
535 if (srp->smk_access == 0)
536 seq_putc(s, '-');
537
538 seq_putc(s, '\n');
Casey Schauflerf7112e62012-05-06 15:22:02 -0700539}
540
541/*
542 * Seq_file read operations for /smack/load
543 */
544
545static void *load2_seq_start(struct seq_file *s, loff_t *pos)
546{
547 return smk_seq_start(s, pos, &smack_rule_list);
548}
549
550static void *load2_seq_next(struct seq_file *s, void *v, loff_t *pos)
551{
552 return smk_seq_next(s, v, pos, &smack_rule_list);
553}
554
555static int load_seq_show(struct seq_file *s, void *v)
556{
557 struct list_head *list = v;
558 struct smack_master_list *smlp =
559 list_entry(list, struct smack_master_list, list);
560
561 smk_rule_show(s, smlp->smk_rule, SMK_LABELLEN);
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800562
563 return 0;
564}
565
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800566static const struct seq_operations load_seq_ops = {
Casey Schauflerf7112e62012-05-06 15:22:02 -0700567 .start = load2_seq_start,
568 .next = load2_seq_next,
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800569 .show = load_seq_show,
Casey Schaufler40809562011-11-10 15:02:22 -0800570 .stop = smk_seq_stop,
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800571};
572
573/**
574 * smk_open_load - open() for /smack/load
575 * @inode: inode structure representing file
576 * @file: "load" file pointer
577 *
578 * For reading, use load_seq_* seq_file reading operations.
579 */
580static int smk_open_load(struct inode *inode, struct file *file)
581{
582 return seq_open(file, &load_seq_ops);
583}
584
585/**
586 * smk_write_load - write() for /smack/load
587 * @file: file pointer, not actually used
588 * @buf: where to get the data from
589 * @count: bytes sent
590 * @ppos: where to start - must be 0
591 *
592 */
593static ssize_t smk_write_load(struct file *file, const char __user *buf,
594 size_t count, loff_t *ppos)
595{
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800596 /*
597 * Must have privilege.
598 * No partial writes.
599 * Enough data must be present.
600 */
Casey Schaufler1880eff2012-06-05 15:28:30 -0700601 if (!smack_privileged(CAP_MAC_ADMIN))
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800602 return -EPERM;
603
Casey Schauflerf7112e62012-05-06 15:22:02 -0700604 return smk_write_rules_list(file, buf, count, ppos, NULL, NULL,
605 SMK_FIXED24_FMT);
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800606}
607
Casey Schauflere114e472008-02-04 22:29:50 -0800608static const struct file_operations smk_load_ops = {
609 .open = smk_open_load,
610 .read = seq_read,
611 .llseek = seq_lseek,
612 .write = smk_write_load,
Ahmed S. Darwishcb622bb2008-03-24 12:29:49 -0700613 .release = seq_release,
Casey Schauflere114e472008-02-04 22:29:50 -0800614};
615
616/**
617 * smk_cipso_doi - initialize the CIPSO domain
618 */
Casey Schaufler30aa4fa2008-04-28 02:13:43 -0700619static void smk_cipso_doi(void)
Casey Schauflere114e472008-02-04 22:29:50 -0800620{
621 int rc;
622 struct cipso_v4_doi *doip;
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500623 struct netlbl_audit nai;
Casey Schauflere114e472008-02-04 22:29:50 -0800624
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500625 smk_netlabel_audit_set(&nai);
Casey Schaufler4bc87e62008-02-15 15:24:25 -0800626
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500627 rc = netlbl_cfg_map_del(NULL, PF_INET, NULL, NULL, &nai);
Casey Schauflere114e472008-02-04 22:29:50 -0800628 if (rc != 0)
629 printk(KERN_WARNING "%s:%d remove rc = %d\n",
630 __func__, __LINE__, rc);
631
632 doip = kmalloc(sizeof(struct cipso_v4_doi), GFP_KERNEL);
633 if (doip == NULL)
634 panic("smack: Failed to initialize cipso DOI.\n");
635 doip->map.std = NULL;
636 doip->doi = smk_cipso_doi_value;
637 doip->type = CIPSO_V4_MAP_PASS;
638 doip->tags[0] = CIPSO_V4_TAG_RBITMAP;
639 for (rc = 1; rc < CIPSO_V4_TAG_MAXCNT; rc++)
640 doip->tags[rc] = CIPSO_V4_TAG_INVALID;
641
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500642 rc = netlbl_cfg_cipsov4_add(doip, &nai);
Paul Mooreb1edeb12008-10-10 10:16:31 -0400643 if (rc != 0) {
Paul Moore6c2e8ac2008-12-31 12:54:11 -0500644 printk(KERN_WARNING "%s:%d cipso add rc = %d\n",
Casey Schauflere114e472008-02-04 22:29:50 -0800645 __func__, __LINE__, rc);
Paul Mooreb1edeb12008-10-10 10:16:31 -0400646 kfree(doip);
Paul Moore6c2e8ac2008-12-31 12:54:11 -0500647 return;
648 }
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500649 rc = netlbl_cfg_cipsov4_map_add(doip->doi, NULL, NULL, NULL, &nai);
Paul Moore6c2e8ac2008-12-31 12:54:11 -0500650 if (rc != 0) {
651 printk(KERN_WARNING "%s:%d map add rc = %d\n",
652 __func__, __LINE__, rc);
653 kfree(doip);
654 return;
Paul Mooreb1edeb12008-10-10 10:16:31 -0400655 }
Casey Schauflere114e472008-02-04 22:29:50 -0800656}
657
Casey Schaufler4bc87e62008-02-15 15:24:25 -0800658/**
659 * smk_unlbl_ambient - initialize the unlabeled domain
Randy Dunlap251a2a92009-02-18 11:42:33 -0800660 * @oldambient: previous domain string
Casey Schaufler4bc87e62008-02-15 15:24:25 -0800661 */
Casey Schaufler30aa4fa2008-04-28 02:13:43 -0700662static void smk_unlbl_ambient(char *oldambient)
Casey Schaufler4bc87e62008-02-15 15:24:25 -0800663{
664 int rc;
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500665 struct netlbl_audit nai;
Casey Schaufler4bc87e62008-02-15 15:24:25 -0800666
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500667 smk_netlabel_audit_set(&nai);
Casey Schaufler4bc87e62008-02-15 15:24:25 -0800668
669 if (oldambient != NULL) {
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500670 rc = netlbl_cfg_map_del(oldambient, PF_INET, NULL, NULL, &nai);
Casey Schaufler4bc87e62008-02-15 15:24:25 -0800671 if (rc != 0)
672 printk(KERN_WARNING "%s:%d remove rc = %d\n",
673 __func__, __LINE__, rc);
674 }
Casey Schauflerf7112e62012-05-06 15:22:02 -0700675 if (smack_net_ambient == NULL)
676 smack_net_ambient = smack_known_floor.smk_known;
Casey Schaufler4bc87e62008-02-15 15:24:25 -0800677
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500678 rc = netlbl_cfg_unlbl_map_add(smack_net_ambient, PF_INET,
679 NULL, NULL, &nai);
Casey Schaufler4bc87e62008-02-15 15:24:25 -0800680 if (rc != 0)
681 printk(KERN_WARNING "%s:%d add rc = %d\n",
682 __func__, __LINE__, rc);
683}
684
Casey Schauflere114e472008-02-04 22:29:50 -0800685/*
686 * Seq_file read operations for /smack/cipso
687 */
688
689static void *cipso_seq_start(struct seq_file *s, loff_t *pos)
690{
Casey Schaufler40809562011-11-10 15:02:22 -0800691 return smk_seq_start(s, pos, &smack_known_list);
Casey Schauflere114e472008-02-04 22:29:50 -0800692}
693
694static void *cipso_seq_next(struct seq_file *s, void *v, loff_t *pos)
695{
Casey Schaufler40809562011-11-10 15:02:22 -0800696 return smk_seq_next(s, v, pos, &smack_known_list);
Casey Schauflere114e472008-02-04 22:29:50 -0800697}
698
699/*
700 * Print cipso labels in format:
701 * label level[/cat[,cat]]
702 */
703static int cipso_seq_show(struct seq_file *s, void *v)
704{
Etienne Basset7198e2e2009-03-24 20:53:24 +0100705 struct list_head *list = v;
706 struct smack_known *skp =
707 list_entry(list, struct smack_known, list);
Casey Schauflerf7112e62012-05-06 15:22:02 -0700708 struct netlbl_lsm_secattr_catmap *cmp = skp->smk_netlabel.attr.mls.cat;
Casey Schauflere114e472008-02-04 22:29:50 -0800709 char sep = '/';
Casey Schauflere114e472008-02-04 22:29:50 -0800710 int i;
Casey Schauflere114e472008-02-04 22:29:50 -0800711
Casey Schauflerf7112e62012-05-06 15:22:02 -0700712 /*
713 * Don't show a label that could not have been set using
714 * /smack/cipso. This is in support of the notion that
715 * anything read from /smack/cipso ought to be writeable
716 * to /smack/cipso.
717 *
718 * /smack/cipso2 should be used instead.
719 */
720 if (strlen(skp->smk_known) >= SMK_LABELLEN)
Casey Schauflere114e472008-02-04 22:29:50 -0800721 return 0;
722
Casey Schauflerf7112e62012-05-06 15:22:02 -0700723 seq_printf(s, "%s %3d", skp->smk_known, skp->smk_netlabel.attr.mls.lvl);
Casey Schauflere114e472008-02-04 22:29:50 -0800724
Casey Schauflerf7112e62012-05-06 15:22:02 -0700725 for (i = netlbl_secattr_catmap_walk(cmp, 0); i >= 0;
726 i = netlbl_secattr_catmap_walk(cmp, i + 1)) {
727 seq_printf(s, "%c%d", sep, i);
728 sep = ',';
729 }
Casey Schauflere114e472008-02-04 22:29:50 -0800730
731 seq_putc(s, '\n');
732
733 return 0;
734}
735
James Morris88e9d342009-09-22 16:43:43 -0700736static const struct seq_operations cipso_seq_ops = {
Casey Schauflere114e472008-02-04 22:29:50 -0800737 .start = cipso_seq_start,
Casey Schauflere114e472008-02-04 22:29:50 -0800738 .next = cipso_seq_next,
739 .show = cipso_seq_show,
Casey Schaufler40809562011-11-10 15:02:22 -0800740 .stop = smk_seq_stop,
Casey Schauflere114e472008-02-04 22:29:50 -0800741};
742
743/**
744 * smk_open_cipso - open() for /smack/cipso
745 * @inode: inode structure representing file
746 * @file: "cipso" file pointer
747 *
748 * Connect our cipso_seq_* operations with /smack/cipso
749 * file_operations
750 */
751static int smk_open_cipso(struct inode *inode, struct file *file)
752{
753 return seq_open(file, &cipso_seq_ops);
754}
755
756/**
Casey Schauflerf7112e62012-05-06 15:22:02 -0700757 * smk_set_cipso - do the work for write() for cipso and cipso2
Randy Dunlap251a2a92009-02-18 11:42:33 -0800758 * @file: file pointer, not actually used
Casey Schauflere114e472008-02-04 22:29:50 -0800759 * @buf: where to get the data from
760 * @count: bytes sent
761 * @ppos: where to start
Casey Schauflerf7112e62012-05-06 15:22:02 -0700762 * @format: /smack/cipso or /smack/cipso2
Casey Schauflere114e472008-02-04 22:29:50 -0800763 *
764 * Accepts only one cipso rule per write call.
765 * Returns number of bytes written or error code, as appropriate
766 */
Casey Schauflerf7112e62012-05-06 15:22:02 -0700767static ssize_t smk_set_cipso(struct file *file, const char __user *buf,
768 size_t count, loff_t *ppos, int format)
Casey Schauflere114e472008-02-04 22:29:50 -0800769{
770 struct smack_known *skp;
Casey Schauflerf7112e62012-05-06 15:22:02 -0700771 struct netlbl_lsm_secattr ncats;
772 char mapcatset[SMK_CIPSOLEN];
Casey Schauflere114e472008-02-04 22:29:50 -0800773 int maplevel;
Casey Schauflerf7112e62012-05-06 15:22:02 -0700774 unsigned int cat;
Casey Schauflere114e472008-02-04 22:29:50 -0800775 int catlen;
776 ssize_t rc = -EINVAL;
777 char *data = NULL;
778 char *rule;
779 int ret;
780 int i;
781
782 /*
783 * Must have privilege.
784 * No partial writes.
785 * Enough data must be present.
786 */
Casey Schaufler1880eff2012-06-05 15:28:30 -0700787 if (!smack_privileged(CAP_MAC_ADMIN))
Casey Schauflere114e472008-02-04 22:29:50 -0800788 return -EPERM;
789 if (*ppos != 0)
790 return -EINVAL;
Casey Schauflerf7112e62012-05-06 15:22:02 -0700791 if (format == SMK_FIXED24_FMT &&
792 (count < SMK_CIPSOMIN || count > SMK_CIPSOMAX))
Casey Schauflere114e472008-02-04 22:29:50 -0800793 return -EINVAL;
794
795 data = kzalloc(count + 1, GFP_KERNEL);
796 if (data == NULL)
797 return -ENOMEM;
798
799 if (copy_from_user(data, buf, count) != 0) {
800 rc = -EFAULT;
801 goto unlockedout;
802 }
803
804 data[count] = '\0';
805 rule = data;
806 /*
807 * Only allow one writer at a time. Writes should be
808 * quite rare and small in any case.
809 */
810 mutex_lock(&smack_cipso_lock);
811
812 skp = smk_import_entry(rule, 0);
813 if (skp == NULL)
814 goto out;
815
Casey Schauflerf7112e62012-05-06 15:22:02 -0700816 if (format == SMK_FIXED24_FMT)
817 rule += SMK_LABELLEN;
818 else
819 rule += strlen(skp->smk_known);
820
Casey Schauflere114e472008-02-04 22:29:50 -0800821 ret = sscanf(rule, "%d", &maplevel);
822 if (ret != 1 || maplevel > SMACK_CIPSO_MAXLEVEL)
823 goto out;
824
825 rule += SMK_DIGITLEN;
826 ret = sscanf(rule, "%d", &catlen);
827 if (ret != 1 || catlen > SMACK_CIPSO_MAXCATNUM)
828 goto out;
829
Casey Schauflerf7112e62012-05-06 15:22:02 -0700830 if (format == SMK_FIXED24_FMT &&
831 count != (SMK_CIPSOMIN + catlen * SMK_DIGITLEN))
Casey Schauflere114e472008-02-04 22:29:50 -0800832 goto out;
833
834 memset(mapcatset, 0, sizeof(mapcatset));
835
836 for (i = 0; i < catlen; i++) {
837 rule += SMK_DIGITLEN;
Casey Schauflerf7112e62012-05-06 15:22:02 -0700838 ret = sscanf(rule, "%u", &cat);
Casey Schauflere114e472008-02-04 22:29:50 -0800839 if (ret != 1 || cat > SMACK_CIPSO_MAXCATVAL)
840 goto out;
841
842 smack_catset_bit(cat, mapcatset);
843 }
844
Casey Schauflerf7112e62012-05-06 15:22:02 -0700845 rc = smk_netlbl_mls(maplevel, mapcatset, &ncats, SMK_CIPSOLEN);
846 if (rc >= 0) {
847 netlbl_secattr_catmap_free(skp->smk_netlabel.attr.mls.cat);
848 skp->smk_netlabel.attr.mls.cat = ncats.attr.mls.cat;
849 skp->smk_netlabel.attr.mls.lvl = ncats.attr.mls.lvl;
850 rc = count;
Casey Schauflere114e472008-02-04 22:29:50 -0800851 }
852
Casey Schauflere114e472008-02-04 22:29:50 -0800853out:
854 mutex_unlock(&smack_cipso_lock);
855unlockedout:
856 kfree(data);
857 return rc;
858}
859
Casey Schauflerf7112e62012-05-06 15:22:02 -0700860/**
861 * smk_write_cipso - write() for /smack/cipso
862 * @file: file pointer, not actually used
863 * @buf: where to get the data from
864 * @count: bytes sent
865 * @ppos: where to start
866 *
867 * Accepts only one cipso rule per write call.
868 * Returns number of bytes written or error code, as appropriate
869 */
870static ssize_t smk_write_cipso(struct file *file, const char __user *buf,
871 size_t count, loff_t *ppos)
872{
873 return smk_set_cipso(file, buf, count, ppos, SMK_FIXED24_FMT);
874}
875
Casey Schauflere114e472008-02-04 22:29:50 -0800876static const struct file_operations smk_cipso_ops = {
877 .open = smk_open_cipso,
878 .read = seq_read,
879 .llseek = seq_lseek,
880 .write = smk_write_cipso,
881 .release = seq_release,
882};
883
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500884/*
Casey Schauflerf7112e62012-05-06 15:22:02 -0700885 * Seq_file read operations for /smack/cipso2
886 */
887
888/*
889 * Print cipso labels in format:
890 * label level[/cat[,cat]]
891 */
892static int cipso2_seq_show(struct seq_file *s, void *v)
893{
894 struct list_head *list = v;
895 struct smack_known *skp =
896 list_entry(list, struct smack_known, list);
897 struct netlbl_lsm_secattr_catmap *cmp = skp->smk_netlabel.attr.mls.cat;
898 char sep = '/';
899 int i;
900
901 seq_printf(s, "%s %3d", skp->smk_known, skp->smk_netlabel.attr.mls.lvl);
902
903 for (i = netlbl_secattr_catmap_walk(cmp, 0); i >= 0;
904 i = netlbl_secattr_catmap_walk(cmp, i + 1)) {
905 seq_printf(s, "%c%d", sep, i);
906 sep = ',';
907 }
908
909 seq_putc(s, '\n');
910
911 return 0;
912}
913
914static const struct seq_operations cipso2_seq_ops = {
915 .start = cipso_seq_start,
916 .next = cipso_seq_next,
917 .show = cipso2_seq_show,
918 .stop = smk_seq_stop,
919};
920
921/**
922 * smk_open_cipso2 - open() for /smack/cipso2
923 * @inode: inode structure representing file
924 * @file: "cipso2" file pointer
925 *
926 * Connect our cipso_seq_* operations with /smack/cipso2
927 * file_operations
928 */
929static int smk_open_cipso2(struct inode *inode, struct file *file)
930{
931 return seq_open(file, &cipso2_seq_ops);
932}
933
934/**
935 * smk_write_cipso2 - write() for /smack/cipso2
936 * @file: file pointer, not actually used
937 * @buf: where to get the data from
938 * @count: bytes sent
939 * @ppos: where to start
940 *
941 * Accepts only one cipso rule per write call.
942 * Returns number of bytes written or error code, as appropriate
943 */
944static ssize_t smk_write_cipso2(struct file *file, const char __user *buf,
945 size_t count, loff_t *ppos)
946{
947 return smk_set_cipso(file, buf, count, ppos, SMK_LONG_FMT);
948}
949
950static const struct file_operations smk_cipso2_ops = {
951 .open = smk_open_cipso2,
952 .read = seq_read,
953 .llseek = seq_lseek,
954 .write = smk_write_cipso2,
955 .release = seq_release,
956};
957
958/*
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500959 * Seq_file read operations for /smack/netlabel
960 */
961
962static void *netlbladdr_seq_start(struct seq_file *s, loff_t *pos)
963{
Casey Schaufler40809562011-11-10 15:02:22 -0800964 return smk_seq_start(s, pos, &smk_netlbladdr_list);
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500965}
966
967static void *netlbladdr_seq_next(struct seq_file *s, void *v, loff_t *pos)
968{
Casey Schaufler40809562011-11-10 15:02:22 -0800969 return smk_seq_next(s, v, pos, &smk_netlbladdr_list);
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500970}
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500971#define BEBITS (sizeof(__be32) * 8)
972
973/*
974 * Print host/label pairs
975 */
976static int netlbladdr_seq_show(struct seq_file *s, void *v)
977{
Etienne Basset7198e2e2009-03-24 20:53:24 +0100978 struct list_head *list = v;
979 struct smk_netlbladdr *skp =
980 list_entry(list, struct smk_netlbladdr, list);
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500981 unsigned char *hp = (char *) &skp->smk_host.sin_addr.s_addr;
etienne113a0e42009-03-04 07:33:51 +0100982 int maskn;
983 u32 temp_mask = be32_to_cpu(skp->smk_mask.s_addr);
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500984
etienne113a0e42009-03-04 07:33:51 +0100985 for (maskn = 0; temp_mask; temp_mask <<= 1, maskn++);
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500986
987 seq_printf(s, "%u.%u.%u.%u/%d %s\n",
988 hp[0], hp[1], hp[2], hp[3], maskn, skp->smk_label);
989
990 return 0;
991}
992
James Morris88e9d342009-09-22 16:43:43 -0700993static const struct seq_operations netlbladdr_seq_ops = {
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500994 .start = netlbladdr_seq_start,
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500995 .next = netlbladdr_seq_next,
996 .show = netlbladdr_seq_show,
Casey Schaufler40809562011-11-10 15:02:22 -0800997 .stop = smk_seq_stop,
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500998};
999
1000/**
1001 * smk_open_netlbladdr - open() for /smack/netlabel
1002 * @inode: inode structure representing file
1003 * @file: "netlabel" file pointer
1004 *
1005 * Connect our netlbladdr_seq_* operations with /smack/netlabel
1006 * file_operations
1007 */
1008static int smk_open_netlbladdr(struct inode *inode, struct file *file)
1009{
1010 return seq_open(file, &netlbladdr_seq_ops);
1011}
1012
1013/**
etienne113a0e42009-03-04 07:33:51 +01001014 * smk_netlbladdr_insert
1015 * @new : netlabel to insert
1016 *
1017 * This helper insert netlabel in the smack_netlbladdrs list
1018 * sorted by netmask length (longest to smallest)
Etienne Basset7198e2e2009-03-24 20:53:24 +01001019 * locked by &smk_netlbladdr_lock in smk_write_netlbladdr
1020 *
etienne113a0e42009-03-04 07:33:51 +01001021 */
1022static void smk_netlbladdr_insert(struct smk_netlbladdr *new)
1023{
Etienne Basset7198e2e2009-03-24 20:53:24 +01001024 struct smk_netlbladdr *m, *m_next;
etienne113a0e42009-03-04 07:33:51 +01001025
Etienne Basset7198e2e2009-03-24 20:53:24 +01001026 if (list_empty(&smk_netlbladdr_list)) {
1027 list_add_rcu(&new->list, &smk_netlbladdr_list);
etienne113a0e42009-03-04 07:33:51 +01001028 return;
1029 }
1030
Jiri Pirko05725f72009-04-14 20:17:16 +02001031 m = list_entry_rcu(smk_netlbladdr_list.next,
1032 struct smk_netlbladdr, list);
Etienne Basset7198e2e2009-03-24 20:53:24 +01001033
etienne113a0e42009-03-04 07:33:51 +01001034 /* the comparison '>' is a bit hacky, but works */
Etienne Basset7198e2e2009-03-24 20:53:24 +01001035 if (new->smk_mask.s_addr > m->smk_mask.s_addr) {
1036 list_add_rcu(&new->list, &smk_netlbladdr_list);
etienne113a0e42009-03-04 07:33:51 +01001037 return;
1038 }
Etienne Basset7198e2e2009-03-24 20:53:24 +01001039
1040 list_for_each_entry_rcu(m, &smk_netlbladdr_list, list) {
1041 if (list_is_last(&m->list, &smk_netlbladdr_list)) {
1042 list_add_rcu(&new->list, &m->list);
etienne113a0e42009-03-04 07:33:51 +01001043 return;
1044 }
Jiri Pirko05725f72009-04-14 20:17:16 +02001045 m_next = list_entry_rcu(m->list.next,
1046 struct smk_netlbladdr, list);
Etienne Basset7198e2e2009-03-24 20:53:24 +01001047 if (new->smk_mask.s_addr > m_next->smk_mask.s_addr) {
1048 list_add_rcu(&new->list, &m->list);
etienne113a0e42009-03-04 07:33:51 +01001049 return;
1050 }
1051 }
1052}
1053
1054
1055/**
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001056 * smk_write_netlbladdr - write() for /smack/netlabel
Randy Dunlap251a2a92009-02-18 11:42:33 -08001057 * @file: file pointer, not actually used
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001058 * @buf: where to get the data from
1059 * @count: bytes sent
1060 * @ppos: where to start
1061 *
1062 * Accepts only one netlbladdr per write call.
1063 * Returns number of bytes written or error code, as appropriate
1064 */
1065static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
1066 size_t count, loff_t *ppos)
1067{
1068 struct smk_netlbladdr *skp;
1069 struct sockaddr_in newname;
Casey Schauflerf7112e62012-05-06 15:22:02 -07001070 char *smack;
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001071 char *sp;
Casey Schauflerf7112e62012-05-06 15:22:02 -07001072 char *data;
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001073 char *host = (char *)&newname.sin_addr.s_addr;
1074 int rc;
1075 struct netlbl_audit audit_info;
1076 struct in_addr mask;
1077 unsigned int m;
Etienne Basset7198e2e2009-03-24 20:53:24 +01001078 int found;
etienne113a0e42009-03-04 07:33:51 +01001079 u32 mask_bits = (1<<31);
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001080 __be32 nsa;
etienne113a0e42009-03-04 07:33:51 +01001081 u32 temp_mask;
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001082
1083 /*
1084 * Must have privilege.
1085 * No partial writes.
1086 * Enough data must be present.
1087 * "<addr/mask, as a.b.c.d/e><space><label>"
1088 * "<addr, as a.b.c.d><space><label>"
1089 */
Casey Schaufler1880eff2012-06-05 15:28:30 -07001090 if (!smack_privileged(CAP_MAC_ADMIN))
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001091 return -EPERM;
1092 if (*ppos != 0)
1093 return -EINVAL;
Casey Schauflerf7112e62012-05-06 15:22:02 -07001094 if (count < SMK_NETLBLADDRMIN)
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001095 return -EINVAL;
Casey Schauflerf7112e62012-05-06 15:22:02 -07001096
1097 data = kzalloc(count + 1, GFP_KERNEL);
1098 if (data == NULL)
1099 return -ENOMEM;
1100
1101 if (copy_from_user(data, buf, count) != 0) {
1102 rc = -EFAULT;
1103 goto free_data_out;
1104 }
1105
1106 smack = kzalloc(count + 1, GFP_KERNEL);
1107 if (smack == NULL) {
1108 rc = -ENOMEM;
1109 goto free_data_out;
1110 }
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001111
1112 data[count] = '\0';
1113
1114 rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd/%d %s",
1115 &host[0], &host[1], &host[2], &host[3], &m, smack);
1116 if (rc != 6) {
1117 rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd %s",
1118 &host[0], &host[1], &host[2], &host[3], smack);
Casey Schauflerf7112e62012-05-06 15:22:02 -07001119 if (rc != 5) {
1120 rc = -EINVAL;
1121 goto free_out;
1122 }
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001123 m = BEBITS;
1124 }
Casey Schauflerf7112e62012-05-06 15:22:02 -07001125 if (m > BEBITS) {
1126 rc = -EINVAL;
1127 goto free_out;
1128 }
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001129
Casey Schauflerf7112e62012-05-06 15:22:02 -07001130 /*
1131 * If smack begins with '-', it is an option, don't import it
1132 */
Etienne Basset43031542009-03-27 17:11:01 -04001133 if (smack[0] != '-') {
1134 sp = smk_import(smack, 0);
Casey Schauflerf7112e62012-05-06 15:22:02 -07001135 if (sp == NULL) {
1136 rc = -EINVAL;
1137 goto free_out;
1138 }
Etienne Basset43031542009-03-27 17:11:01 -04001139 } else {
1140 /* check known options */
1141 if (strcmp(smack, smack_cipso_option) == 0)
1142 sp = (char *)smack_cipso_option;
Casey Schauflerf7112e62012-05-06 15:22:02 -07001143 else {
1144 rc = -EINVAL;
1145 goto free_out;
1146 }
Etienne Basset43031542009-03-27 17:11:01 -04001147 }
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001148
etienne113a0e42009-03-04 07:33:51 +01001149 for (temp_mask = 0; m > 0; m--) {
1150 temp_mask |= mask_bits;
1151 mask_bits >>= 1;
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001152 }
etienne113a0e42009-03-04 07:33:51 +01001153 mask.s_addr = cpu_to_be32(temp_mask);
1154
1155 newname.sin_addr.s_addr &= mask.s_addr;
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001156 /*
1157 * Only allow one writer at a time. Writes should be
1158 * quite rare and small in any case.
1159 */
1160 mutex_lock(&smk_netlbladdr_lock);
1161
1162 nsa = newname.sin_addr.s_addr;
etienne113a0e42009-03-04 07:33:51 +01001163 /* try to find if the prefix is already in the list */
Etienne Basset7198e2e2009-03-24 20:53:24 +01001164 found = 0;
1165 list_for_each_entry_rcu(skp, &smk_netlbladdr_list, list) {
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001166 if (skp->smk_host.sin_addr.s_addr == nsa &&
Etienne Basset7198e2e2009-03-24 20:53:24 +01001167 skp->smk_mask.s_addr == mask.s_addr) {
1168 found = 1;
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001169 break;
Etienne Basset7198e2e2009-03-24 20:53:24 +01001170 }
1171 }
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001172 smk_netlabel_audit_set(&audit_info);
1173
Etienne Basset7198e2e2009-03-24 20:53:24 +01001174 if (found == 0) {
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001175 skp = kzalloc(sizeof(*skp), GFP_KERNEL);
1176 if (skp == NULL)
1177 rc = -ENOMEM;
1178 else {
1179 rc = 0;
1180 skp->smk_host.sin_addr.s_addr = newname.sin_addr.s_addr;
1181 skp->smk_mask.s_addr = mask.s_addr;
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001182 skp->smk_label = sp;
etienne113a0e42009-03-04 07:33:51 +01001183 smk_netlbladdr_insert(skp);
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001184 }
1185 } else {
Etienne Basset43031542009-03-27 17:11:01 -04001186 /* we delete the unlabeled entry, only if the previous label
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001187 * wasn't the special CIPSO option */
Etienne Basset43031542009-03-27 17:11:01 -04001188 if (skp->smk_label != smack_cipso_option)
1189 rc = netlbl_cfg_unlbl_static_del(&init_net, NULL,
1190 &skp->smk_host.sin_addr, &skp->smk_mask,
1191 PF_INET, &audit_info);
1192 else
1193 rc = 0;
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001194 skp->smk_label = sp;
1195 }
1196
1197 /*
1198 * Now tell netlabel about the single label nature of
1199 * this host so that incoming packets get labeled.
Etienne Basset43031542009-03-27 17:11:01 -04001200 * but only if we didn't get the special CIPSO option
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001201 */
Etienne Basset43031542009-03-27 17:11:01 -04001202 if (rc == 0 && sp != smack_cipso_option)
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001203 rc = netlbl_cfg_unlbl_static_add(&init_net, NULL,
1204 &skp->smk_host.sin_addr, &skp->smk_mask, PF_INET,
1205 smack_to_secid(skp->smk_label), &audit_info);
1206
1207 if (rc == 0)
1208 rc = count;
1209
1210 mutex_unlock(&smk_netlbladdr_lock);
1211
Casey Schauflerf7112e62012-05-06 15:22:02 -07001212free_out:
1213 kfree(smack);
1214free_data_out:
1215 kfree(data);
1216
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001217 return rc;
1218}
1219
1220static const struct file_operations smk_netlbladdr_ops = {
1221 .open = smk_open_netlbladdr,
1222 .read = seq_read,
1223 .llseek = seq_lseek,
1224 .write = smk_write_netlbladdr,
1225 .release = seq_release,
1226};
1227
Casey Schauflere114e472008-02-04 22:29:50 -08001228/**
1229 * smk_read_doi - read() for /smack/doi
1230 * @filp: file pointer, not actually used
1231 * @buf: where to put the result
1232 * @count: maximum to send along
1233 * @ppos: where to start
1234 *
1235 * Returns number of bytes read or error code, as appropriate
1236 */
1237static ssize_t smk_read_doi(struct file *filp, char __user *buf,
1238 size_t count, loff_t *ppos)
1239{
1240 char temp[80];
1241 ssize_t rc;
1242
1243 if (*ppos != 0)
1244 return 0;
1245
1246 sprintf(temp, "%d", smk_cipso_doi_value);
1247 rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
1248
1249 return rc;
1250}
1251
1252/**
1253 * smk_write_doi - write() for /smack/doi
Randy Dunlap251a2a92009-02-18 11:42:33 -08001254 * @file: file pointer, not actually used
Casey Schauflere114e472008-02-04 22:29:50 -08001255 * @buf: where to get the data from
1256 * @count: bytes sent
1257 * @ppos: where to start
1258 *
1259 * Returns number of bytes written or error code, as appropriate
1260 */
1261static ssize_t smk_write_doi(struct file *file, const char __user *buf,
1262 size_t count, loff_t *ppos)
1263{
1264 char temp[80];
1265 int i;
1266
Casey Schaufler1880eff2012-06-05 15:28:30 -07001267 if (!smack_privileged(CAP_MAC_ADMIN))
Casey Schauflere114e472008-02-04 22:29:50 -08001268 return -EPERM;
1269
1270 if (count >= sizeof(temp) || count == 0)
1271 return -EINVAL;
1272
1273 if (copy_from_user(temp, buf, count) != 0)
1274 return -EFAULT;
1275
1276 temp[count] = '\0';
1277
1278 if (sscanf(temp, "%d", &i) != 1)
1279 return -EINVAL;
1280
1281 smk_cipso_doi_value = i;
1282
1283 smk_cipso_doi();
1284
1285 return count;
1286}
1287
1288static const struct file_operations smk_doi_ops = {
1289 .read = smk_read_doi,
1290 .write = smk_write_doi,
Arnd Bergmann6038f372010-08-15 18:52:59 +02001291 .llseek = default_llseek,
Casey Schauflere114e472008-02-04 22:29:50 -08001292};
1293
1294/**
1295 * smk_read_direct - read() for /smack/direct
1296 * @filp: file pointer, not actually used
1297 * @buf: where to put the result
1298 * @count: maximum to send along
1299 * @ppos: where to start
1300 *
1301 * Returns number of bytes read or error code, as appropriate
1302 */
1303static ssize_t smk_read_direct(struct file *filp, char __user *buf,
1304 size_t count, loff_t *ppos)
1305{
1306 char temp[80];
1307 ssize_t rc;
1308
1309 if (*ppos != 0)
1310 return 0;
1311
1312 sprintf(temp, "%d", smack_cipso_direct);
1313 rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
1314
1315 return rc;
1316}
1317
1318/**
1319 * smk_write_direct - write() for /smack/direct
Randy Dunlap251a2a92009-02-18 11:42:33 -08001320 * @file: file pointer, not actually used
Casey Schauflere114e472008-02-04 22:29:50 -08001321 * @buf: where to get the data from
1322 * @count: bytes sent
1323 * @ppos: where to start
1324 *
1325 * Returns number of bytes written or error code, as appropriate
1326 */
1327static ssize_t smk_write_direct(struct file *file, const char __user *buf,
1328 size_t count, loff_t *ppos)
1329{
Casey Schauflerf7112e62012-05-06 15:22:02 -07001330 struct smack_known *skp;
Casey Schauflere114e472008-02-04 22:29:50 -08001331 char temp[80];
1332 int i;
1333
Casey Schaufler1880eff2012-06-05 15:28:30 -07001334 if (!smack_privileged(CAP_MAC_ADMIN))
Casey Schauflere114e472008-02-04 22:29:50 -08001335 return -EPERM;
1336
1337 if (count >= sizeof(temp) || count == 0)
1338 return -EINVAL;
1339
1340 if (copy_from_user(temp, buf, count) != 0)
1341 return -EFAULT;
1342
1343 temp[count] = '\0';
1344
1345 if (sscanf(temp, "%d", &i) != 1)
1346 return -EINVAL;
1347
Casey Schauflerf7112e62012-05-06 15:22:02 -07001348 /*
1349 * Don't do anything if the value hasn't actually changed.
1350 * If it is changing reset the level on entries that were
1351 * set up to be direct when they were created.
1352 */
1353 if (smack_cipso_direct != i) {
1354 mutex_lock(&smack_known_lock);
1355 list_for_each_entry_rcu(skp, &smack_known_list, list)
1356 if (skp->smk_netlabel.attr.mls.lvl ==
1357 smack_cipso_direct)
1358 skp->smk_netlabel.attr.mls.lvl = i;
1359 smack_cipso_direct = i;
1360 mutex_unlock(&smack_known_lock);
1361 }
Casey Schauflere114e472008-02-04 22:29:50 -08001362
1363 return count;
1364}
1365
1366static const struct file_operations smk_direct_ops = {
1367 .read = smk_read_direct,
1368 .write = smk_write_direct,
Arnd Bergmann6038f372010-08-15 18:52:59 +02001369 .llseek = default_llseek,
Casey Schauflere114e472008-02-04 22:29:50 -08001370};
1371
1372/**
Casey Schauflerf7112e62012-05-06 15:22:02 -07001373 * smk_read_mapped - read() for /smack/mapped
1374 * @filp: file pointer, not actually used
1375 * @buf: where to put the result
1376 * @count: maximum to send along
1377 * @ppos: where to start
1378 *
1379 * Returns number of bytes read or error code, as appropriate
1380 */
1381static ssize_t smk_read_mapped(struct file *filp, char __user *buf,
1382 size_t count, loff_t *ppos)
1383{
1384 char temp[80];
1385 ssize_t rc;
1386
1387 if (*ppos != 0)
1388 return 0;
1389
1390 sprintf(temp, "%d", smack_cipso_mapped);
1391 rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
1392
1393 return rc;
1394}
1395
1396/**
1397 * smk_write_mapped - write() for /smack/mapped
1398 * @file: file pointer, not actually used
1399 * @buf: where to get the data from
1400 * @count: bytes sent
1401 * @ppos: where to start
1402 *
1403 * Returns number of bytes written or error code, as appropriate
1404 */
1405static ssize_t smk_write_mapped(struct file *file, const char __user *buf,
1406 size_t count, loff_t *ppos)
1407{
1408 struct smack_known *skp;
1409 char temp[80];
1410 int i;
1411
Casey Schaufler1880eff2012-06-05 15:28:30 -07001412 if (!smack_privileged(CAP_MAC_ADMIN))
Casey Schauflerf7112e62012-05-06 15:22:02 -07001413 return -EPERM;
1414
1415 if (count >= sizeof(temp) || count == 0)
1416 return -EINVAL;
1417
1418 if (copy_from_user(temp, buf, count) != 0)
1419 return -EFAULT;
1420
1421 temp[count] = '\0';
1422
1423 if (sscanf(temp, "%d", &i) != 1)
1424 return -EINVAL;
1425
1426 /*
1427 * Don't do anything if the value hasn't actually changed.
1428 * If it is changing reset the level on entries that were
1429 * set up to be mapped when they were created.
1430 */
1431 if (smack_cipso_mapped != i) {
1432 mutex_lock(&smack_known_lock);
1433 list_for_each_entry_rcu(skp, &smack_known_list, list)
1434 if (skp->smk_netlabel.attr.mls.lvl ==
1435 smack_cipso_mapped)
1436 skp->smk_netlabel.attr.mls.lvl = i;
1437 smack_cipso_mapped = i;
1438 mutex_unlock(&smack_known_lock);
1439 }
1440
1441 return count;
1442}
1443
1444static const struct file_operations smk_mapped_ops = {
1445 .read = smk_read_mapped,
1446 .write = smk_write_mapped,
1447 .llseek = default_llseek,
1448};
1449
1450/**
Casey Schauflere114e472008-02-04 22:29:50 -08001451 * smk_read_ambient - read() for /smack/ambient
1452 * @filp: file pointer, not actually used
1453 * @buf: where to put the result
1454 * @cn: maximum to send along
1455 * @ppos: where to start
1456 *
1457 * Returns number of bytes read or error code, as appropriate
1458 */
1459static ssize_t smk_read_ambient(struct file *filp, char __user *buf,
1460 size_t cn, loff_t *ppos)
1461{
1462 ssize_t rc;
Casey Schauflere114e472008-02-04 22:29:50 -08001463 int asize;
1464
1465 if (*ppos != 0)
1466 return 0;
1467 /*
1468 * Being careful to avoid a problem in the case where
1469 * smack_net_ambient gets changed in midstream.
Casey Schauflere114e472008-02-04 22:29:50 -08001470 */
Casey Schaufler4bc87e62008-02-15 15:24:25 -08001471 mutex_lock(&smack_ambient_lock);
Casey Schauflere114e472008-02-04 22:29:50 -08001472
Casey Schaufler4bc87e62008-02-15 15:24:25 -08001473 asize = strlen(smack_net_ambient) + 1;
Casey Schauflere114e472008-02-04 22:29:50 -08001474
Casey Schaufler4bc87e62008-02-15 15:24:25 -08001475 if (cn >= asize)
1476 rc = simple_read_from_buffer(buf, cn, ppos,
1477 smack_net_ambient, asize);
1478 else
1479 rc = -EINVAL;
1480
1481 mutex_unlock(&smack_ambient_lock);
Casey Schauflere114e472008-02-04 22:29:50 -08001482
1483 return rc;
1484}
1485
1486/**
1487 * smk_write_ambient - write() for /smack/ambient
Randy Dunlap251a2a92009-02-18 11:42:33 -08001488 * @file: file pointer, not actually used
Casey Schauflere114e472008-02-04 22:29:50 -08001489 * @buf: where to get the data from
1490 * @count: bytes sent
1491 * @ppos: where to start
1492 *
1493 * Returns number of bytes written or error code, as appropriate
1494 */
1495static ssize_t smk_write_ambient(struct file *file, const char __user *buf,
1496 size_t count, loff_t *ppos)
1497{
Casey Schaufler4bc87e62008-02-15 15:24:25 -08001498 char *oldambient;
Casey Schauflerf7112e62012-05-06 15:22:02 -07001499 char *smack = NULL;
1500 char *data;
1501 int rc = count;
Casey Schauflere114e472008-02-04 22:29:50 -08001502
Casey Schaufler1880eff2012-06-05 15:28:30 -07001503 if (!smack_privileged(CAP_MAC_ADMIN))
Casey Schauflere114e472008-02-04 22:29:50 -08001504 return -EPERM;
1505
Casey Schauflerf7112e62012-05-06 15:22:02 -07001506 data = kzalloc(count + 1, GFP_KERNEL);
1507 if (data == NULL)
1508 return -ENOMEM;
Casey Schauflere114e472008-02-04 22:29:50 -08001509
Casey Schauflerf7112e62012-05-06 15:22:02 -07001510 if (copy_from_user(data, buf, count) != 0) {
1511 rc = -EFAULT;
1512 goto out;
1513 }
Casey Schauflere114e472008-02-04 22:29:50 -08001514
Casey Schauflerf7112e62012-05-06 15:22:02 -07001515 smack = smk_import(data, count);
1516 if (smack == NULL) {
1517 rc = -EINVAL;
1518 goto out;
1519 }
Casey Schauflere114e472008-02-04 22:29:50 -08001520
Casey Schaufler4bc87e62008-02-15 15:24:25 -08001521 mutex_lock(&smack_ambient_lock);
1522
1523 oldambient = smack_net_ambient;
Casey Schauflere114e472008-02-04 22:29:50 -08001524 smack_net_ambient = smack;
Casey Schaufler4bc87e62008-02-15 15:24:25 -08001525 smk_unlbl_ambient(oldambient);
1526
1527 mutex_unlock(&smack_ambient_lock);
Casey Schauflere114e472008-02-04 22:29:50 -08001528
Casey Schauflerf7112e62012-05-06 15:22:02 -07001529out:
1530 kfree(data);
1531 return rc;
Casey Schauflere114e472008-02-04 22:29:50 -08001532}
1533
1534static const struct file_operations smk_ambient_ops = {
1535 .read = smk_read_ambient,
1536 .write = smk_write_ambient,
Arnd Bergmann6038f372010-08-15 18:52:59 +02001537 .llseek = default_llseek,
Casey Schauflere114e472008-02-04 22:29:50 -08001538};
1539
Casey Schaufler15446232008-07-30 15:37:11 -07001540/**
1541 * smk_read_onlycap - read() for /smack/onlycap
1542 * @filp: file pointer, not actually used
1543 * @buf: where to put the result
1544 * @cn: maximum to send along
1545 * @ppos: where to start
1546 *
1547 * Returns number of bytes read or error code, as appropriate
1548 */
1549static ssize_t smk_read_onlycap(struct file *filp, char __user *buf,
1550 size_t cn, loff_t *ppos)
1551{
1552 char *smack = "";
1553 ssize_t rc = -EINVAL;
1554 int asize;
1555
1556 if (*ppos != 0)
1557 return 0;
1558
1559 if (smack_onlycap != NULL)
1560 smack = smack_onlycap;
1561
1562 asize = strlen(smack) + 1;
1563
1564 if (cn >= asize)
1565 rc = simple_read_from_buffer(buf, cn, ppos, smack, asize);
1566
1567 return rc;
1568}
1569
1570/**
1571 * smk_write_onlycap - write() for /smack/onlycap
Randy Dunlap251a2a92009-02-18 11:42:33 -08001572 * @file: file pointer, not actually used
Casey Schaufler15446232008-07-30 15:37:11 -07001573 * @buf: where to get the data from
1574 * @count: bytes sent
1575 * @ppos: where to start
1576 *
1577 * Returns number of bytes written or error code, as appropriate
1578 */
1579static ssize_t smk_write_onlycap(struct file *file, const char __user *buf,
1580 size_t count, loff_t *ppos)
1581{
Casey Schauflerf7112e62012-05-06 15:22:02 -07001582 char *data;
Casey Schaufler676dac42010-12-02 06:43:39 -08001583 char *sp = smk_of_task(current->cred->security);
Casey Schauflerf7112e62012-05-06 15:22:02 -07001584 int rc = count;
Casey Schaufler15446232008-07-30 15:37:11 -07001585
Casey Schaufler1880eff2012-06-05 15:28:30 -07001586 if (!smack_privileged(CAP_MAC_ADMIN))
Casey Schaufler15446232008-07-30 15:37:11 -07001587 return -EPERM;
1588
1589 /*
1590 * This can be done using smk_access() but is done
1591 * explicitly for clarity. The smk_access() implementation
1592 * would use smk_access(smack_onlycap, MAY_WRITE)
1593 */
1594 if (smack_onlycap != NULL && smack_onlycap != sp)
1595 return -EPERM;
1596
Casey Schauflerf7112e62012-05-06 15:22:02 -07001597 data = kzalloc(count, GFP_KERNEL);
1598 if (data == NULL)
1599 return -ENOMEM;
Casey Schaufler15446232008-07-30 15:37:11 -07001600
1601 /*
1602 * Should the null string be passed in unset the onlycap value.
1603 * This seems like something to be careful with as usually
1604 * smk_import only expects to return NULL for errors. It
1605 * is usually the case that a nullstring or "\n" would be
1606 * bad to pass to smk_import but in fact this is useful here.
Casey Schauflerf7112e62012-05-06 15:22:02 -07001607 *
1608 * smk_import will also reject a label beginning with '-',
1609 * so "-usecapabilities" will also work.
Casey Schaufler15446232008-07-30 15:37:11 -07001610 */
Casey Schauflerf7112e62012-05-06 15:22:02 -07001611 if (copy_from_user(data, buf, count) != 0)
1612 rc = -EFAULT;
1613 else
1614 smack_onlycap = smk_import(data, count);
Casey Schaufler15446232008-07-30 15:37:11 -07001615
Casey Schauflerf7112e62012-05-06 15:22:02 -07001616 kfree(data);
1617 return rc;
Casey Schaufler15446232008-07-30 15:37:11 -07001618}
1619
1620static const struct file_operations smk_onlycap_ops = {
1621 .read = smk_read_onlycap,
1622 .write = smk_write_onlycap,
Arnd Bergmann6038f372010-08-15 18:52:59 +02001623 .llseek = default_llseek,
Casey Schaufler15446232008-07-30 15:37:11 -07001624};
1625
Casey Schauflere114e472008-02-04 22:29:50 -08001626/**
Etienne Bassetecfcc532009-04-08 20:40:06 +02001627 * smk_read_logging - read() for /smack/logging
1628 * @filp: file pointer, not actually used
1629 * @buf: where to put the result
1630 * @cn: maximum to send along
1631 * @ppos: where to start
1632 *
1633 * Returns number of bytes read or error code, as appropriate
1634 */
1635static ssize_t smk_read_logging(struct file *filp, char __user *buf,
1636 size_t count, loff_t *ppos)
1637{
1638 char temp[32];
1639 ssize_t rc;
1640
1641 if (*ppos != 0)
1642 return 0;
1643
1644 sprintf(temp, "%d\n", log_policy);
1645 rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
1646 return rc;
1647}
1648
1649/**
1650 * smk_write_logging - write() for /smack/logging
1651 * @file: file pointer, not actually used
1652 * @buf: where to get the data from
1653 * @count: bytes sent
1654 * @ppos: where to start
1655 *
1656 * Returns number of bytes written or error code, as appropriate
1657 */
1658static ssize_t smk_write_logging(struct file *file, const char __user *buf,
1659 size_t count, loff_t *ppos)
1660{
1661 char temp[32];
1662 int i;
1663
Casey Schaufler1880eff2012-06-05 15:28:30 -07001664 if (!smack_privileged(CAP_MAC_ADMIN))
Etienne Bassetecfcc532009-04-08 20:40:06 +02001665 return -EPERM;
1666
1667 if (count >= sizeof(temp) || count == 0)
1668 return -EINVAL;
1669
1670 if (copy_from_user(temp, buf, count) != 0)
1671 return -EFAULT;
1672
1673 temp[count] = '\0';
1674
1675 if (sscanf(temp, "%d", &i) != 1)
1676 return -EINVAL;
1677 if (i < 0 || i > 3)
1678 return -EINVAL;
1679 log_policy = i;
1680 return count;
1681}
1682
1683
1684
1685static const struct file_operations smk_logging_ops = {
1686 .read = smk_read_logging,
1687 .write = smk_write_logging,
Arnd Bergmann6038f372010-08-15 18:52:59 +02001688 .llseek = default_llseek,
Etienne Bassetecfcc532009-04-08 20:40:06 +02001689};
Casey Schaufler7898e1f2011-01-17 08:05:27 -08001690
1691/*
1692 * Seq_file read operations for /smack/load-self
1693 */
1694
1695static void *load_self_seq_start(struct seq_file *s, loff_t *pos)
1696{
1697 struct task_smack *tsp = current_security();
1698
Casey Schaufler40809562011-11-10 15:02:22 -08001699 return smk_seq_start(s, pos, &tsp->smk_rules);
Casey Schaufler7898e1f2011-01-17 08:05:27 -08001700}
1701
1702static void *load_self_seq_next(struct seq_file *s, void *v, loff_t *pos)
1703{
1704 struct task_smack *tsp = current_security();
Casey Schaufler7898e1f2011-01-17 08:05:27 -08001705
Casey Schaufler40809562011-11-10 15:02:22 -08001706 return smk_seq_next(s, v, pos, &tsp->smk_rules);
Casey Schaufler7898e1f2011-01-17 08:05:27 -08001707}
1708
1709static int load_self_seq_show(struct seq_file *s, void *v)
1710{
1711 struct list_head *list = v;
1712 struct smack_rule *srp =
1713 list_entry(list, struct smack_rule, list);
1714
Casey Schauflerf7112e62012-05-06 15:22:02 -07001715 smk_rule_show(s, srp, SMK_LABELLEN);
Casey Schaufler7898e1f2011-01-17 08:05:27 -08001716
1717 return 0;
1718}
1719
Casey Schaufler7898e1f2011-01-17 08:05:27 -08001720static const struct seq_operations load_self_seq_ops = {
1721 .start = load_self_seq_start,
1722 .next = load_self_seq_next,
1723 .show = load_self_seq_show,
Casey Schaufler40809562011-11-10 15:02:22 -08001724 .stop = smk_seq_stop,
Casey Schaufler7898e1f2011-01-17 08:05:27 -08001725};
1726
1727
1728/**
Casey Schauflerf7112e62012-05-06 15:22:02 -07001729 * smk_open_load_self - open() for /smack/load-self2
Casey Schaufler7898e1f2011-01-17 08:05:27 -08001730 * @inode: inode structure representing file
1731 * @file: "load" file pointer
1732 *
1733 * For reading, use load_seq_* seq_file reading operations.
1734 */
1735static int smk_open_load_self(struct inode *inode, struct file *file)
1736{
1737 return seq_open(file, &load_self_seq_ops);
1738}
1739
1740/**
1741 * smk_write_load_self - write() for /smack/load-self
1742 * @file: file pointer, not actually used
1743 * @buf: where to get the data from
1744 * @count: bytes sent
1745 * @ppos: where to start - must be 0
1746 *
1747 */
1748static ssize_t smk_write_load_self(struct file *file, const char __user *buf,
1749 size_t count, loff_t *ppos)
1750{
1751 struct task_smack *tsp = current_security();
1752
Casey Schauflerf7112e62012-05-06 15:22:02 -07001753 return smk_write_rules_list(file, buf, count, ppos, &tsp->smk_rules,
1754 &tsp->smk_rules_lock, SMK_FIXED24_FMT);
Casey Schaufler7898e1f2011-01-17 08:05:27 -08001755}
1756
1757static const struct file_operations smk_load_self_ops = {
1758 .open = smk_open_load_self,
1759 .read = seq_read,
1760 .llseek = seq_lseek,
1761 .write = smk_write_load_self,
1762 .release = seq_release,
1763};
Jarkko Sakkinen828716c2011-09-08 10:12:01 +03001764
1765/**
Casey Schauflerf7112e62012-05-06 15:22:02 -07001766 * smk_user_access - handle access check transaction
1767 * @file: file pointer
1768 * @buf: data from user space
1769 * @count: bytes sent
1770 * @ppos: where to start - must be 0
1771 */
1772static ssize_t smk_user_access(struct file *file, const char __user *buf,
1773 size_t count, loff_t *ppos, int format)
1774{
1775 struct smack_rule rule;
1776 char *data;
1777 char *cod;
1778 int res;
1779
1780 data = simple_transaction_get(file, buf, count);
1781 if (IS_ERR(data))
1782 return PTR_ERR(data);
1783
1784 if (format == SMK_FIXED24_FMT) {
1785 if (count < SMK_LOADLEN)
1786 return -EINVAL;
1787 res = smk_parse_rule(data, &rule, 0);
1788 } else {
1789 /*
1790 * Copy the data to make sure the string is terminated.
1791 */
1792 cod = kzalloc(count + 1, GFP_KERNEL);
1793 if (cod == NULL)
1794 return -ENOMEM;
1795 memcpy(cod, data, count);
1796 cod[count] = '\0';
1797 res = smk_parse_long_rule(cod, &rule, 0);
1798 kfree(cod);
1799 }
1800
1801 if (res)
1802 return -EINVAL;
1803
1804 res = smk_access(rule.smk_subject, rule.smk_object, rule.smk_access,
1805 NULL);
1806 data[0] = res == 0 ? '1' : '0';
1807 data[1] = '\0';
1808
1809 simple_transaction_set(file, 2);
1810
1811 if (format == SMK_FIXED24_FMT)
1812 return SMK_LOADLEN;
1813 return count;
1814}
1815
1816/**
Jarkko Sakkinen828716c2011-09-08 10:12:01 +03001817 * smk_write_access - handle access check transaction
1818 * @file: file pointer
1819 * @buf: data from user space
1820 * @count: bytes sent
1821 * @ppos: where to start - must be 0
1822 */
1823static ssize_t smk_write_access(struct file *file, const char __user *buf,
1824 size_t count, loff_t *ppos)
1825{
Casey Schauflerf7112e62012-05-06 15:22:02 -07001826 return smk_user_access(file, buf, count, ppos, SMK_FIXED24_FMT);
Jarkko Sakkinen828716c2011-09-08 10:12:01 +03001827}
1828
1829static const struct file_operations smk_access_ops = {
1830 .write = smk_write_access,
1831 .read = simple_transaction_read,
1832 .release = simple_transaction_release,
1833 .llseek = generic_file_llseek,
1834};
1835
Casey Schauflerf7112e62012-05-06 15:22:02 -07001836
1837/*
1838 * Seq_file read operations for /smack/load2
1839 */
1840
1841static int load2_seq_show(struct seq_file *s, void *v)
1842{
1843 struct list_head *list = v;
1844 struct smack_master_list *smlp =
1845 list_entry(list, struct smack_master_list, list);
1846
1847 smk_rule_show(s, smlp->smk_rule, SMK_LONGLABEL);
1848
1849 return 0;
1850}
1851
1852static const struct seq_operations load2_seq_ops = {
1853 .start = load2_seq_start,
1854 .next = load2_seq_next,
1855 .show = load2_seq_show,
1856 .stop = smk_seq_stop,
1857};
1858
1859/**
1860 * smk_open_load2 - open() for /smack/load2
1861 * @inode: inode structure representing file
1862 * @file: "load2" file pointer
1863 *
1864 * For reading, use load2_seq_* seq_file reading operations.
1865 */
1866static int smk_open_load2(struct inode *inode, struct file *file)
1867{
1868 return seq_open(file, &load2_seq_ops);
1869}
1870
1871/**
1872 * smk_write_load2 - write() for /smack/load2
1873 * @file: file pointer, not actually used
1874 * @buf: where to get the data from
1875 * @count: bytes sent
1876 * @ppos: where to start - must be 0
1877 *
1878 */
1879static ssize_t smk_write_load2(struct file *file, const char __user *buf,
1880 size_t count, loff_t *ppos)
1881{
1882 /*
1883 * Must have privilege.
1884 */
Casey Schaufler1880eff2012-06-05 15:28:30 -07001885 if (!smack_privileged(CAP_MAC_ADMIN))
Casey Schauflerf7112e62012-05-06 15:22:02 -07001886 return -EPERM;
1887
1888 return smk_write_rules_list(file, buf, count, ppos, NULL, NULL,
1889 SMK_LONG_FMT);
1890}
1891
1892static const struct file_operations smk_load2_ops = {
1893 .open = smk_open_load2,
1894 .read = seq_read,
1895 .llseek = seq_lseek,
1896 .write = smk_write_load2,
1897 .release = seq_release,
1898};
1899
1900/*
1901 * Seq_file read operations for /smack/load-self2
1902 */
1903
1904static void *load_self2_seq_start(struct seq_file *s, loff_t *pos)
1905{
1906 struct task_smack *tsp = current_security();
1907
1908 return smk_seq_start(s, pos, &tsp->smk_rules);
1909}
1910
1911static void *load_self2_seq_next(struct seq_file *s, void *v, loff_t *pos)
1912{
1913 struct task_smack *tsp = current_security();
1914
1915 return smk_seq_next(s, v, pos, &tsp->smk_rules);
1916}
1917
1918static int load_self2_seq_show(struct seq_file *s, void *v)
1919{
1920 struct list_head *list = v;
1921 struct smack_rule *srp =
1922 list_entry(list, struct smack_rule, list);
1923
1924 smk_rule_show(s, srp, SMK_LONGLABEL);
1925
1926 return 0;
1927}
1928
1929static const struct seq_operations load_self2_seq_ops = {
1930 .start = load_self2_seq_start,
1931 .next = load_self2_seq_next,
1932 .show = load_self2_seq_show,
1933 .stop = smk_seq_stop,
1934};
1935
1936/**
1937 * smk_open_load_self2 - open() for /smack/load-self2
1938 * @inode: inode structure representing file
1939 * @file: "load" file pointer
1940 *
1941 * For reading, use load_seq_* seq_file reading operations.
1942 */
1943static int smk_open_load_self2(struct inode *inode, struct file *file)
1944{
1945 return seq_open(file, &load_self2_seq_ops);
1946}
1947
1948/**
1949 * smk_write_load_self2 - write() for /smack/load-self2
1950 * @file: file pointer, not actually used
1951 * @buf: where to get the data from
1952 * @count: bytes sent
1953 * @ppos: where to start - must be 0
1954 *
1955 */
1956static ssize_t smk_write_load_self2(struct file *file, const char __user *buf,
1957 size_t count, loff_t *ppos)
1958{
1959 struct task_smack *tsp = current_security();
1960
1961 return smk_write_rules_list(file, buf, count, ppos, &tsp->smk_rules,
1962 &tsp->smk_rules_lock, SMK_LONG_FMT);
1963}
1964
1965static const struct file_operations smk_load_self2_ops = {
1966 .open = smk_open_load_self2,
1967 .read = seq_read,
1968 .llseek = seq_lseek,
1969 .write = smk_write_load_self2,
1970 .release = seq_release,
1971};
1972
1973/**
1974 * smk_write_access2 - handle access check transaction
1975 * @file: file pointer
1976 * @buf: data from user space
1977 * @count: bytes sent
1978 * @ppos: where to start - must be 0
1979 */
1980static ssize_t smk_write_access2(struct file *file, const char __user *buf,
1981 size_t count, loff_t *ppos)
1982{
1983 return smk_user_access(file, buf, count, ppos, SMK_LONG_FMT);
1984}
1985
1986static const struct file_operations smk_access2_ops = {
1987 .write = smk_write_access2,
1988 .read = simple_transaction_read,
1989 .release = simple_transaction_release,
1990 .llseek = generic_file_llseek,
1991};
1992
Etienne Bassetecfcc532009-04-08 20:40:06 +02001993/**
Casey Schauflere114e472008-02-04 22:29:50 -08001994 * smk_fill_super - fill the /smackfs superblock
1995 * @sb: the empty superblock
1996 * @data: unused
1997 * @silent: unused
1998 *
1999 * Fill in the well known entries for /smack
2000 *
2001 * Returns 0 on success, an error code on failure
2002 */
2003static int smk_fill_super(struct super_block *sb, void *data, int silent)
2004{
2005 int rc;
2006 struct inode *root_inode;
2007
2008 static struct tree_descr smack_files[] = {
Casey Schaufler7898e1f2011-01-17 08:05:27 -08002009 [SMK_LOAD] = {
2010 "load", &smk_load_ops, S_IRUGO|S_IWUSR},
2011 [SMK_CIPSO] = {
2012 "cipso", &smk_cipso_ops, S_IRUGO|S_IWUSR},
2013 [SMK_DOI] = {
2014 "doi", &smk_doi_ops, S_IRUGO|S_IWUSR},
2015 [SMK_DIRECT] = {
2016 "direct", &smk_direct_ops, S_IRUGO|S_IWUSR},
2017 [SMK_AMBIENT] = {
2018 "ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR},
2019 [SMK_NETLBLADDR] = {
2020 "netlabel", &smk_netlbladdr_ops, S_IRUGO|S_IWUSR},
2021 [SMK_ONLYCAP] = {
2022 "onlycap", &smk_onlycap_ops, S_IRUGO|S_IWUSR},
2023 [SMK_LOGGING] = {
2024 "logging", &smk_logging_ops, S_IRUGO|S_IWUSR},
2025 [SMK_LOAD_SELF] = {
2026 "load-self", &smk_load_self_ops, S_IRUGO|S_IWUGO},
Jarkko Sakkinen828716c2011-09-08 10:12:01 +03002027 [SMK_ACCESSES] = {
Jarkko Sakkinen0e94ae12011-10-18 21:21:36 +03002028 "access", &smk_access_ops, S_IRUGO|S_IWUGO},
Casey Schauflerf7112e62012-05-06 15:22:02 -07002029 [SMK_MAPPED] = {
2030 "mapped", &smk_mapped_ops, S_IRUGO|S_IWUSR},
2031 [SMK_LOAD2] = {
2032 "load2", &smk_load2_ops, S_IRUGO|S_IWUSR},
2033 [SMK_LOAD_SELF2] = {
2034 "load-self2", &smk_load_self2_ops, S_IRUGO|S_IWUGO},
2035 [SMK_ACCESS2] = {
2036 "access2", &smk_access2_ops, S_IRUGO|S_IWUGO},
2037 [SMK_CIPSO2] = {
2038 "cipso2", &smk_cipso2_ops, S_IRUGO|S_IWUSR},
Casey Schaufler7898e1f2011-01-17 08:05:27 -08002039 /* last one */
2040 {""}
Casey Schauflere114e472008-02-04 22:29:50 -08002041 };
2042
2043 rc = simple_fill_super(sb, SMACK_MAGIC, smack_files);
2044 if (rc != 0) {
2045 printk(KERN_ERR "%s failed %d while creating inodes\n",
2046 __func__, rc);
2047 return rc;
2048 }
2049
2050 root_inode = sb->s_root->d_inode;
Casey Schauflere114e472008-02-04 22:29:50 -08002051
2052 return 0;
2053}
2054
2055/**
Al Virofc14f2f2010-07-25 01:48:30 +04002056 * smk_mount - get the smackfs superblock
Casey Schauflere114e472008-02-04 22:29:50 -08002057 * @fs_type: passed along without comment
2058 * @flags: passed along without comment
2059 * @dev_name: passed along without comment
2060 * @data: passed along without comment
Casey Schauflere114e472008-02-04 22:29:50 -08002061 *
2062 * Just passes everything along.
2063 *
2064 * Returns what the lower level code does.
2065 */
Al Virofc14f2f2010-07-25 01:48:30 +04002066static struct dentry *smk_mount(struct file_system_type *fs_type,
2067 int flags, const char *dev_name, void *data)
Casey Schauflere114e472008-02-04 22:29:50 -08002068{
Al Virofc14f2f2010-07-25 01:48:30 +04002069 return mount_single(fs_type, flags, data, smk_fill_super);
Casey Schauflere114e472008-02-04 22:29:50 -08002070}
2071
2072static struct file_system_type smk_fs_type = {
2073 .name = "smackfs",
Al Virofc14f2f2010-07-25 01:48:30 +04002074 .mount = smk_mount,
Casey Schauflere114e472008-02-04 22:29:50 -08002075 .kill_sb = kill_litter_super,
2076};
2077
2078static struct vfsmount *smackfs_mount;
2079
Casey Schauflerf7112e62012-05-06 15:22:02 -07002080static int __init smk_preset_netlabel(struct smack_known *skp)
2081{
2082 skp->smk_netlabel.domain = skp->smk_known;
2083 skp->smk_netlabel.flags =
2084 NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL;
2085 return smk_netlbl_mls(smack_cipso_direct, skp->smk_known,
2086 &skp->smk_netlabel, strlen(skp->smk_known));
2087}
2088
Casey Schauflere114e472008-02-04 22:29:50 -08002089/**
2090 * init_smk_fs - get the smackfs superblock
2091 *
2092 * register the smackfs
2093 *
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02002094 * Do not register smackfs if Smack wasn't enabled
2095 * on boot. We can not put this method normally under the
2096 * smack_init() code path since the security subsystem get
2097 * initialized before the vfs caches.
2098 *
2099 * Returns true if we were not chosen on boot or if
2100 * we were chosen and filesystem registration succeeded.
Casey Schauflere114e472008-02-04 22:29:50 -08002101 */
2102static int __init init_smk_fs(void)
2103{
2104 int err;
Casey Schauflerf7112e62012-05-06 15:22:02 -07002105 int rc;
Casey Schauflere114e472008-02-04 22:29:50 -08002106
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02002107 if (!security_module_enable(&smack_ops))
2108 return 0;
2109
Casey Schauflere114e472008-02-04 22:29:50 -08002110 err = register_filesystem(&smk_fs_type);
2111 if (!err) {
2112 smackfs_mount = kern_mount(&smk_fs_type);
2113 if (IS_ERR(smackfs_mount)) {
2114 printk(KERN_ERR "smackfs: could not mount!\n");
2115 err = PTR_ERR(smackfs_mount);
2116 smackfs_mount = NULL;
2117 }
2118 }
2119
Casey Schauflere114e472008-02-04 22:29:50 -08002120 smk_cipso_doi();
Casey Schaufler4bc87e62008-02-15 15:24:25 -08002121 smk_unlbl_ambient(NULL);
Casey Schauflere114e472008-02-04 22:29:50 -08002122
Casey Schauflerf7112e62012-05-06 15:22:02 -07002123 rc = smk_preset_netlabel(&smack_known_floor);
2124 if (err == 0 && rc < 0)
2125 err = rc;
2126 rc = smk_preset_netlabel(&smack_known_hat);
2127 if (err == 0 && rc < 0)
2128 err = rc;
2129 rc = smk_preset_netlabel(&smack_known_huh);
2130 if (err == 0 && rc < 0)
2131 err = rc;
2132 rc = smk_preset_netlabel(&smack_known_invalid);
2133 if (err == 0 && rc < 0)
2134 err = rc;
2135 rc = smk_preset_netlabel(&smack_known_star);
2136 if (err == 0 && rc < 0)
2137 err = rc;
2138 rc = smk_preset_netlabel(&smack_known_web);
2139 if (err == 0 && rc < 0)
2140 err = rc;
2141
Casey Schauflere114e472008-02-04 22:29:50 -08002142 return err;
2143}
2144
2145__initcall(init_smk_fs);