blob: deb3d3bfbbf3e4bb71e82049914aa7acf2e62b7b [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 Schaufler958d2c22013-04-02 11:41:18 -070029#include <linux/magic.h>
Casey Schauflere114e472008-02-04 22:29:50 -080030#include "smack.h"
31
32/*
33 * smackfs pseudo filesystem.
34 */
35
36enum smk_inos {
37 SMK_ROOT_INO = 2,
38 SMK_LOAD = 3, /* load policy */
39 SMK_CIPSO = 4, /* load label -> CIPSO mapping */
40 SMK_DOI = 5, /* CIPSO DOI */
41 SMK_DIRECT = 6, /* CIPSO level indicating direct label */
42 SMK_AMBIENT = 7, /* internet ambient label */
Casey Schaufler6d3dc072008-12-31 12:54:12 -050043 SMK_NETLBLADDR = 8, /* single label hosts */
Casey Schaufler15446232008-07-30 15:37:11 -070044 SMK_ONLYCAP = 9, /* the only "capable" label */
Etienne Bassetecfcc532009-04-08 20:40:06 +020045 SMK_LOGGING = 10, /* logging */
Casey Schaufler7898e1f2011-01-17 08:05:27 -080046 SMK_LOAD_SELF = 11, /* task specific rules */
Jarkko Sakkinen828716c2011-09-08 10:12:01 +030047 SMK_ACCESSES = 12, /* access policy */
Casey Schauflerf7112e62012-05-06 15:22:02 -070048 SMK_MAPPED = 13, /* CIPSO level indicating mapped label */
49 SMK_LOAD2 = 14, /* load policy with long labels */
50 SMK_LOAD_SELF2 = 15, /* load task specific rules with long labels */
51 SMK_ACCESS2 = 16, /* make an access check with long labels */
52 SMK_CIPSO2 = 17, /* load long label -> CIPSO mapping */
Rafal Krypa449543b2012-07-11 17:49:30 +020053 SMK_REVOKE_SUBJ = 18, /* set rules with subject label to '-' */
Rafal Krypae05b6f92013-01-10 19:42:00 +010054 SMK_CHANGE_RULE = 19, /* change or add rules (long labels) */
Casey Schaufler00f84f32013-12-23 11:07:10 -080055 SMK_SYSLOG = 20, /* change syslog label) */
Lukasz Pawelczyk66867812014-03-11 17:07:06 +010056 SMK_PTRACE = 21, /* set ptrace rule */
Casey Schauflerbf4b2fe2015-03-21 18:26:40 -070057#ifdef CONFIG_SECURITY_SMACK_BRINGUP
58 SMK_UNCONFINED = 22, /* define an unconfined label */
59#endif
Casey Schauflere114e472008-02-04 22:29:50 -080060};
61
62/*
63 * List locks
64 */
Casey Schauflere114e472008-02-04 22:29:50 -080065static DEFINE_MUTEX(smack_cipso_lock);
Casey Schaufler4bc87e62008-02-15 15:24:25 -080066static DEFINE_MUTEX(smack_ambient_lock);
Casey Schaufler00f84f32013-12-23 11:07:10 -080067static DEFINE_MUTEX(smack_syslog_lock);
Casey Schaufler6d3dc072008-12-31 12:54:12 -050068static DEFINE_MUTEX(smk_netlbladdr_lock);
Casey Schauflere114e472008-02-04 22:29:50 -080069
70/*
71 * This is the "ambient" label for network traffic.
72 * If it isn't somehow marked, use this.
73 * It can be reset via smackfs/ambient
74 */
Casey Schaufler2f823ff2013-05-22 18:43:03 -070075struct smack_known *smack_net_ambient;
Casey Schauflere114e472008-02-04 22:29:50 -080076
77/*
Casey Schauflere114e472008-02-04 22:29:50 -080078 * This is the level in a CIPSO header that indicates a
79 * smack label is contained directly in the category set.
80 * It can be reset via smackfs/direct
81 */
82int smack_cipso_direct = SMACK_CIPSO_DIRECT_DEFAULT;
83
Casey Schaufler15446232008-07-30 15:37:11 -070084/*
Casey Schauflerf7112e62012-05-06 15:22:02 -070085 * This is the level in a CIPSO header that indicates a
86 * secid is contained directly in the category set.
87 * It can be reset via smackfs/mapped
88 */
89int smack_cipso_mapped = SMACK_CIPSO_MAPPED_DEFAULT;
90
91/*
Casey Schaufler15446232008-07-30 15:37:11 -070092 * Unless a process is running with this label even
93 * having CAP_MAC_OVERRIDE isn't enough to grant
94 * privilege to violate MAC policy. If no label is
95 * designated (the NULL case) capabilities apply to
96 * everyone. It is expected that the hat (^) label
97 * will be used if any label is used.
98 */
Casey Schaufler00f84f32013-12-23 11:07:10 -080099struct smack_known *smack_onlycap;
100
Casey Schauflerbf4b2fe2015-03-21 18:26:40 -0700101#ifdef CONFIG_SECURITY_SMACK_BRINGUP
102/*
103 * Allow one label to be unconfined. This is for
104 * debugging and application bring-up purposes only.
105 * It is bad and wrong, but everyone seems to expect
106 * to have it.
107 */
108struct smack_known *smack_unconfined;
109#endif
110
Casey Schaufler00f84f32013-12-23 11:07:10 -0800111/*
112 * If this value is set restrict syslog use to the label specified.
113 * It can be reset via smackfs/syslog
114 */
115struct smack_known *smack_syslog_label;
Casey Schaufler15446232008-07-30 15:37:11 -0700116
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500117/*
Lukasz Pawelczyk66867812014-03-11 17:07:06 +0100118 * Ptrace current rule
119 * SMACK_PTRACE_DEFAULT regular smack ptrace rules (/proc based)
120 * SMACK_PTRACE_EXACT labels must match, but can be overriden with
121 * CAP_SYS_PTRACE
122 * SMACK_PTRACE_DRACONIAN lables must match, CAP_SYS_PTRACE has no effect
123 */
124int smack_ptrace_rule = SMACK_PTRACE_DEFAULT;
125
126/*
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500127 * Certain IP addresses may be designated as single label hosts.
128 * Packets are sent there unlabeled, but only from tasks that
129 * can write to the specified label.
130 */
Etienne Basset7198e2e2009-03-24 20:53:24 +0100131
132LIST_HEAD(smk_netlbladdr_list);
Casey Schaufler272cd7a2011-09-20 12:24:36 -0700133
134/*
135 * Rule lists are maintained for each label.
Casey Schauflerf7112e62012-05-06 15:22:02 -0700136 * This master list is just for reading /smack/load and /smack/load2.
Casey Schaufler272cd7a2011-09-20 12:24:36 -0700137 */
138struct smack_master_list {
139 struct list_head list;
140 struct smack_rule *smk_rule;
141};
142
Etienne Basset7198e2e2009-03-24 20:53:24 +0100143LIST_HEAD(smack_rule_list);
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500144
Rafal Krypae05b6f92013-01-10 19:42:00 +0100145struct smack_parsed_rule {
Casey Schaufler2f823ff2013-05-22 18:43:03 -0700146 struct smack_known *smk_subject;
Lukasz Pawelczyk21c7eae2014-08-29 17:02:55 +0200147 struct smack_known *smk_object;
Rafal Krypae05b6f92013-01-10 19:42:00 +0100148 int smk_access1;
149 int smk_access2;
150};
151
Casey Schauflere114e472008-02-04 22:29:50 -0800152static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT;
Casey Schauflere114e472008-02-04 22:29:50 -0800153
Lukasz Pawelczyk21c7eae2014-08-29 17:02:55 +0200154struct smack_known smack_cipso_option = {
155 .smk_known = SMACK_CIPSO_OPTION,
156 .smk_secid = 0,
157};
Etienne Basset43031542009-03-27 17:11:01 -0400158
Casey Schauflere114e472008-02-04 22:29:50 -0800159/*
Casey Schauflere114e472008-02-04 22:29:50 -0800160 * Values for parsing cipso rules
161 * SMK_DIGITLEN: Length of a digit field in a rule.
Ahmed S. Darwishb500ce82008-03-13 12:32:34 -0700162 * SMK_CIPSOMIN: Minimum possible cipso rule length.
163 * SMK_CIPSOMAX: Maximum possible cipso rule length.
Casey Schauflere114e472008-02-04 22:29:50 -0800164 */
165#define SMK_DIGITLEN 4
Ahmed S. Darwishb500ce82008-03-13 12:32:34 -0700166#define SMK_CIPSOMIN (SMK_LABELLEN + 2 * SMK_DIGITLEN)
167#define SMK_CIPSOMAX (SMK_CIPSOMIN + SMACK_CIPSO_MAXCATNUM * SMK_DIGITLEN)
168
169/*
170 * Values for parsing MAC rules
171 * SMK_ACCESS: Maximum possible combination of access permissions
172 * SMK_ACCESSLEN: Maximum length for a rule access field
173 * SMK_LOADLEN: Smack rule length
174 */
Jarkko Sakkinen5c6d1122010-12-07 13:34:01 +0200175#define SMK_OACCESS "rwxa"
Casey Schauflerc0ab6e52013-10-11 18:06:39 -0700176#define SMK_ACCESS "rwxatl"
Jarkko Sakkinen5c6d1122010-12-07 13:34:01 +0200177#define SMK_OACCESSLEN (sizeof(SMK_OACCESS) - 1)
178#define SMK_ACCESSLEN (sizeof(SMK_ACCESS) - 1)
179#define SMK_OLOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_OACCESSLEN)
180#define SMK_LOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_ACCESSLEN)
Ahmed S. Darwishb500ce82008-03-13 12:32:34 -0700181
Casey Schauflerf7112e62012-05-06 15:22:02 -0700182/*
183 * Stricly for CIPSO level manipulation.
184 * Set the category bit number in a smack label sized buffer.
185 */
186static inline void smack_catset_bit(unsigned int cat, char *catsetp)
187{
188 if (cat == 0 || cat > (SMK_CIPSOLEN * 8))
189 return;
190
191 catsetp[(cat - 1) / 8] |= 0x80 >> ((cat - 1) % 8);
192}
193
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500194/**
195 * smk_netlabel_audit_set - fill a netlbl_audit struct
196 * @nap: structure to fill
197 */
198static void smk_netlabel_audit_set(struct netlbl_audit *nap)
199{
Casey Schaufler2f823ff2013-05-22 18:43:03 -0700200 struct smack_known *skp = smk_of_current();
201
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500202 nap->loginuid = audit_get_loginuid(current);
203 nap->sessionid = audit_get_sessionid(current);
Casey Schaufler2f823ff2013-05-22 18:43:03 -0700204 nap->secid = skp->smk_secid;
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500205}
206
207/*
Casey Schauflerf7112e62012-05-06 15:22:02 -0700208 * Value for parsing single label host rules
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500209 * "1.2.3.4 X"
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500210 */
211#define SMK_NETLBLADDRMIN 9
Casey Schauflere114e472008-02-04 22:29:50 -0800212
Casey Schauflere114e472008-02-04 22:29:50 -0800213/**
Rafal Krypae05b6f92013-01-10 19:42:00 +0100214 * smk_set_access - add a rule to the rule list or replace an old rule
215 * @srp: the rule to add or replace
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800216 * @rule_list: the list of rules
217 * @rule_lock: the rule list lock
Rafal Krypae05b6f92013-01-10 19:42:00 +0100218 * @global: if non-zero, indicates a global rule
Casey Schauflere114e472008-02-04 22:29:50 -0800219 *
220 * Looks through the current subject/object/access list for
221 * the subject/object pair and replaces the access that was
222 * there. If the pair isn't found add it with the specified
223 * access.
Sergio Luis81ea7142008-12-22 01:16:15 -0300224 *
225 * Returns 0 if nothing goes wrong or -ENOMEM if it fails
226 * during the allocation of the new pair to add.
Casey Schauflere114e472008-02-04 22:29:50 -0800227 */
Rafal Krypae05b6f92013-01-10 19:42:00 +0100228static int smk_set_access(struct smack_parsed_rule *srp,
229 struct list_head *rule_list,
230 struct mutex *rule_lock, int global)
Casey Schauflere114e472008-02-04 22:29:50 -0800231{
Etienne Basset7198e2e2009-03-24 20:53:24 +0100232 struct smack_rule *sp;
Rafal Krypae05b6f92013-01-10 19:42:00 +0100233 struct smack_master_list *smlp;
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800234 int found = 0;
Rafal Krypae05b6f92013-01-10 19:42:00 +0100235 int rc = 0;
Casey Schauflere114e472008-02-04 22:29:50 -0800236
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800237 mutex_lock(rule_lock);
238
Casey Schaufler272cd7a2011-09-20 12:24:36 -0700239 /*
240 * Because the object label is less likely to match
241 * than the subject label check it first
242 */
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800243 list_for_each_entry_rcu(sp, rule_list, list) {
Casey Schaufler272cd7a2011-09-20 12:24:36 -0700244 if (sp->smk_object == srp->smk_object &&
245 sp->smk_subject == srp->smk_subject) {
Etienne Basset7198e2e2009-03-24 20:53:24 +0100246 found = 1;
Rafal Krypae05b6f92013-01-10 19:42:00 +0100247 sp->smk_access |= srp->smk_access1;
248 sp->smk_access &= ~srp->smk_access2;
Casey Schauflere114e472008-02-04 22:29:50 -0800249 break;
250 }
Casey Schauflere114e472008-02-04 22:29:50 -0800251 }
252
Rafal Krypae05b6f92013-01-10 19:42:00 +0100253 if (found == 0) {
254 sp = kzalloc(sizeof(*sp), GFP_KERNEL);
255 if (sp == NULL) {
256 rc = -ENOMEM;
257 goto out;
258 }
259
260 sp->smk_subject = srp->smk_subject;
261 sp->smk_object = srp->smk_object;
262 sp->smk_access = srp->smk_access1 & ~srp->smk_access2;
263
264 list_add_rcu(&sp->list, rule_list);
265 /*
266 * If this is a global as opposed to self and a new rule
267 * it needs to get added for reporting.
268 */
269 if (global) {
270 smlp = kzalloc(sizeof(*smlp), GFP_KERNEL);
271 if (smlp != NULL) {
272 smlp->smk_rule = sp;
273 list_add_rcu(&smlp->list, &smack_rule_list);
274 } else
275 rc = -ENOMEM;
276 }
277 }
278
279out:
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800280 mutex_unlock(rule_lock);
Rafal Krypae05b6f92013-01-10 19:42:00 +0100281 return rc;
282}
Casey Schauflere114e472008-02-04 22:29:50 -0800283
Rafal Krypae05b6f92013-01-10 19:42:00 +0100284/**
285 * smk_perm_from_str - parse smack accesses from a text string
286 * @string: a text string that contains a Smack accesses code
287 *
288 * Returns an integer with respective bits set for specified accesses.
289 */
290static int smk_perm_from_str(const char *string)
291{
292 int perm = 0;
293 const char *cp;
294
295 for (cp = string; ; cp++)
296 switch (*cp) {
297 case '-':
298 break;
299 case 'r':
300 case 'R':
301 perm |= MAY_READ;
302 break;
303 case 'w':
304 case 'W':
305 perm |= MAY_WRITE;
306 break;
307 case 'x':
308 case 'X':
309 perm |= MAY_EXEC;
310 break;
311 case 'a':
312 case 'A':
313 perm |= MAY_APPEND;
314 break;
315 case 't':
316 case 'T':
317 perm |= MAY_TRANSMUTE;
318 break;
Casey Schauflerc0ab6e52013-10-11 18:06:39 -0700319 case 'l':
320 case 'L':
321 perm |= MAY_LOCK;
322 break;
Casey Schauflerd166c802014-08-27 14:51:27 -0700323 case 'b':
324 case 'B':
325 perm |= MAY_BRINGUP;
326 break;
Rafal Krypae05b6f92013-01-10 19:42:00 +0100327 default:
328 return perm;
329 }
Casey Schauflere114e472008-02-04 22:29:50 -0800330}
331
332/**
Casey Schauflerf7112e62012-05-06 15:22:02 -0700333 * smk_fill_rule - Fill Smack rule from strings
334 * @subject: subject label string
335 * @object: object label string
Rafal Krypae05b6f92013-01-10 19:42:00 +0100336 * @access1: access string
337 * @access2: string with permissions to be removed
Jarkko Sakkinen0e94ae12011-10-18 21:21:36 +0300338 * @rule: Smack rule
339 * @import: if non-zero, import labels
Casey Schaufler35187212012-06-18 19:01:36 -0700340 * @len: label length limit
Casey Schauflerf7112e62012-05-06 15:22:02 -0700341 *
Jarkko Sakkinen398ce072013-11-28 19:16:46 +0200342 * Returns 0 on success, -EINVAL on failure and -ENOENT when either subject
343 * or object is missing.
Jarkko Sakkinen828716c2011-09-08 10:12:01 +0300344 */
Casey Schauflerf7112e62012-05-06 15:22:02 -0700345static int smk_fill_rule(const char *subject, const char *object,
Rafal Krypae05b6f92013-01-10 19:42:00 +0100346 const char *access1, const char *access2,
347 struct smack_parsed_rule *rule, int import,
348 int len)
Jarkko Sakkinen828716c2011-09-08 10:12:01 +0300349{
Casey Schauflerf7112e62012-05-06 15:22:02 -0700350 const char *cp;
Jarkko Sakkinen0e94ae12011-10-18 21:21:36 +0300351 struct smack_known *skp;
Jarkko Sakkinen828716c2011-09-08 10:12:01 +0300352
Jarkko Sakkinen0e94ae12011-10-18 21:21:36 +0300353 if (import) {
Casey Schaufler2f823ff2013-05-22 18:43:03 -0700354 rule->smk_subject = smk_import_entry(subject, len);
Jarkko Sakkinen0e94ae12011-10-18 21:21:36 +0300355 if (rule->smk_subject == NULL)
Jarkko Sakkinen398ce072013-11-28 19:16:46 +0200356 return -EINVAL;
Jarkko Sakkinen0e94ae12011-10-18 21:21:36 +0300357
Lukasz Pawelczyk21c7eae2014-08-29 17:02:55 +0200358 rule->smk_object = smk_import_entry(object, len);
Jarkko Sakkinen0e94ae12011-10-18 21:21:36 +0300359 if (rule->smk_object == NULL)
Jarkko Sakkinen398ce072013-11-28 19:16:46 +0200360 return -EINVAL;
Jarkko Sakkinen0e94ae12011-10-18 21:21:36 +0300361 } else {
Casey Schaufler35187212012-06-18 19:01:36 -0700362 cp = smk_parse_smack(subject, len);
Casey Schauflerf7112e62012-05-06 15:22:02 -0700363 if (cp == NULL)
Jarkko Sakkinen398ce072013-11-28 19:16:46 +0200364 return -EINVAL;
Casey Schauflerf7112e62012-05-06 15:22:02 -0700365 skp = smk_find_entry(cp);
366 kfree(cp);
Jarkko Sakkinen0e94ae12011-10-18 21:21:36 +0300367 if (skp == NULL)
Jarkko Sakkinen398ce072013-11-28 19:16:46 +0200368 return -ENOENT;
Casey Schaufler2f823ff2013-05-22 18:43:03 -0700369 rule->smk_subject = skp;
Jarkko Sakkinen0e94ae12011-10-18 21:21:36 +0300370
Casey Schaufler35187212012-06-18 19:01:36 -0700371 cp = smk_parse_smack(object, len);
Casey Schauflerf7112e62012-05-06 15:22:02 -0700372 if (cp == NULL)
Jarkko Sakkinen398ce072013-11-28 19:16:46 +0200373 return -EINVAL;
Casey Schauflerf7112e62012-05-06 15:22:02 -0700374 skp = smk_find_entry(cp);
375 kfree(cp);
Jarkko Sakkinen0e94ae12011-10-18 21:21:36 +0300376 if (skp == NULL)
Jarkko Sakkinen398ce072013-11-28 19:16:46 +0200377 return -ENOENT;
Lukasz Pawelczyk21c7eae2014-08-29 17:02:55 +0200378 rule->smk_object = skp;
Jarkko Sakkinen0e94ae12011-10-18 21:21:36 +0300379 }
Jarkko Sakkinen828716c2011-09-08 10:12:01 +0300380
Rafal Krypae05b6f92013-01-10 19:42:00 +0100381 rule->smk_access1 = smk_perm_from_str(access1);
382 if (access2)
383 rule->smk_access2 = smk_perm_from_str(access2);
384 else
385 rule->smk_access2 = ~rule->smk_access1;
Jarkko Sakkinen828716c2011-09-08 10:12:01 +0300386
Casey Schaufler35187212012-06-18 19:01:36 -0700387 return 0;
Jarkko Sakkinen828716c2011-09-08 10:12:01 +0300388}
389
390/**
Casey Schauflerf7112e62012-05-06 15:22:02 -0700391 * smk_parse_rule - parse Smack rule from load string
392 * @data: string to be parsed whose size is SMK_LOADLEN
393 * @rule: Smack rule
394 * @import: if non-zero, import labels
395 *
396 * Returns 0 on success, -1 on errors.
397 */
Rafal Krypae05b6f92013-01-10 19:42:00 +0100398static int smk_parse_rule(const char *data, struct smack_parsed_rule *rule,
399 int import)
Casey Schauflerf7112e62012-05-06 15:22:02 -0700400{
401 int rc;
402
403 rc = smk_fill_rule(data, data + SMK_LABELLEN,
Rafal Krypae05b6f92013-01-10 19:42:00 +0100404 data + SMK_LABELLEN + SMK_LABELLEN, NULL, rule,
405 import, SMK_LABELLEN);
Casey Schauflerf7112e62012-05-06 15:22:02 -0700406 return rc;
407}
408
409/**
410 * smk_parse_long_rule - parse Smack rule from rule string
411 * @data: string to be parsed, null terminated
Rafal Krypae05b6f92013-01-10 19:42:00 +0100412 * @rule: Will be filled with Smack parsed rule
Casey Schauflerf7112e62012-05-06 15:22:02 -0700413 * @import: if non-zero, import labels
Rafal Krypa10289b02013-08-09 11:47:07 +0200414 * @tokens: numer of substrings expected in data
Casey Schauflerf7112e62012-05-06 15:22:02 -0700415 *
Rafal Krypa10289b02013-08-09 11:47:07 +0200416 * Returns number of processed bytes on success, -1 on failure.
Casey Schauflerf7112e62012-05-06 15:22:02 -0700417 */
Rafal Krypa10289b02013-08-09 11:47:07 +0200418static ssize_t smk_parse_long_rule(char *data, struct smack_parsed_rule *rule,
419 int import, int tokens)
Casey Schauflerf7112e62012-05-06 15:22:02 -0700420{
Rafal Krypa10289b02013-08-09 11:47:07 +0200421 ssize_t cnt = 0;
422 char *tok[4];
Jarkko Sakkinen398ce072013-11-28 19:16:46 +0200423 int rc;
Rafal Krypa10289b02013-08-09 11:47:07 +0200424 int i;
Casey Schauflerf7112e62012-05-06 15:22:02 -0700425
Rafal Krypa10289b02013-08-09 11:47:07 +0200426 /*
427 * Parsing the rule in-place, filling all white-spaces with '\0'
428 */
429 for (i = 0; i < tokens; ++i) {
430 while (isspace(data[cnt]))
431 data[cnt++] = '\0';
Alan Cox3b9fc372012-07-26 14:47:11 -0700432
Rafal Krypa10289b02013-08-09 11:47:07 +0200433 if (data[cnt] == '\0')
434 /* Unexpected end of data */
435 return -1;
Casey Schauflerf7112e62012-05-06 15:22:02 -0700436
Rafal Krypa10289b02013-08-09 11:47:07 +0200437 tok[i] = data + cnt;
438
439 while (data[cnt] && !isspace(data[cnt]))
440 ++cnt;
Rafal Krypae05b6f92013-01-10 19:42:00 +0100441 }
Rafal Krypa10289b02013-08-09 11:47:07 +0200442 while (isspace(data[cnt]))
443 data[cnt++] = '\0';
Casey Schauflerf7112e62012-05-06 15:22:02 -0700444
Rafal Krypa10289b02013-08-09 11:47:07 +0200445 while (i < 4)
446 tok[i++] = NULL;
447
Jarkko Sakkinen398ce072013-11-28 19:16:46 +0200448 rc = smk_fill_rule(tok[0], tok[1], tok[2], tok[3], rule, import, 0);
449 return rc == 0 ? cnt : rc;
Casey Schauflerf7112e62012-05-06 15:22:02 -0700450}
451
452#define SMK_FIXED24_FMT 0 /* Fixed 24byte label format */
453#define SMK_LONG_FMT 1 /* Variable long label format */
Rafal Krypae05b6f92013-01-10 19:42:00 +0100454#define SMK_CHANGE_FMT 2 /* Rule modification format */
Casey Schauflerf7112e62012-05-06 15:22:02 -0700455/**
456 * smk_write_rules_list - write() for any /smack rule file
Randy Dunlap251a2a92009-02-18 11:42:33 -0800457 * @file: file pointer, not actually used
Casey Schauflere114e472008-02-04 22:29:50 -0800458 * @buf: where to get the data from
459 * @count: bytes sent
460 * @ppos: where to start - must be 0
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800461 * @rule_list: the list of rules to write to
462 * @rule_lock: lock for the rule list
Rafal Krypae05b6f92013-01-10 19:42:00 +0100463 * @format: /smack/load or /smack/load2 or /smack/change-rule format.
Casey Schauflere114e472008-02-04 22:29:50 -0800464 *
465 * Get one smack access rule from above.
Casey Schauflerf7112e62012-05-06 15:22:02 -0700466 * The format for SMK_LONG_FMT is:
467 * "subject<whitespace>object<whitespace>access[<whitespace>...]"
468 * The format for SMK_FIXED24_FMT is exactly:
469 * "subject object rwxat"
Rafal Krypae05b6f92013-01-10 19:42:00 +0100470 * The format for SMK_CHANGE_FMT is:
471 * "subject<whitespace>object<whitespace>
472 * acc_enable<whitespace>acc_disable[<whitespace>...]"
Casey Schauflere114e472008-02-04 22:29:50 -0800473 */
Casey Schauflerf7112e62012-05-06 15:22:02 -0700474static ssize_t smk_write_rules_list(struct file *file, const char __user *buf,
475 size_t count, loff_t *ppos,
476 struct list_head *rule_list,
477 struct mutex *rule_lock, int format)
Casey Schauflere114e472008-02-04 22:29:50 -0800478{
Tomasz Stanislawski470043b2013-06-06 09:30:50 +0200479 struct smack_parsed_rule rule;
Casey Schauflere114e472008-02-04 22:29:50 -0800480 char *data;
Rafal Krypa10289b02013-08-09 11:47:07 +0200481 int rc;
482 int trunc = 0;
483 int tokens;
484 ssize_t cnt = 0;
Casey Schauflere114e472008-02-04 22:29:50 -0800485
486 /*
Casey Schauflere114e472008-02-04 22:29:50 -0800487 * No partial writes.
488 * Enough data must be present.
489 */
Jarkko Sakkinen5c6d1122010-12-07 13:34:01 +0200490 if (*ppos != 0)
491 return -EINVAL;
Casey Schauflere114e472008-02-04 22:29:50 -0800492
Casey Schauflerf7112e62012-05-06 15:22:02 -0700493 if (format == SMK_FIXED24_FMT) {
494 /*
495 * Minor hack for backward compatibility
496 */
Casey Schauflerc0ab6e52013-10-11 18:06:39 -0700497 if (count < SMK_OLOADLEN || count > SMK_LOADLEN)
Casey Schauflerf7112e62012-05-06 15:22:02 -0700498 return -EINVAL;
Rafal Krypa10289b02013-08-09 11:47:07 +0200499 } else {
500 if (count >= PAGE_SIZE) {
501 count = PAGE_SIZE - 1;
502 trunc = 1;
503 }
504 }
Casey Schauflerf7112e62012-05-06 15:22:02 -0700505
Rafal Krypa10289b02013-08-09 11:47:07 +0200506 data = kmalloc(count + 1, GFP_KERNEL);
Casey Schauflere114e472008-02-04 22:29:50 -0800507 if (data == NULL)
508 return -ENOMEM;
509
510 if (copy_from_user(data, buf, count) != 0) {
511 rc = -EFAULT;
512 goto out;
513 }
514
Rafal Krypa10289b02013-08-09 11:47:07 +0200515 /*
516 * In case of parsing only part of user buf,
517 * avoid having partial rule at the data buffer
518 */
519 if (trunc) {
520 while (count > 0 && (data[count - 1] != '\n'))
521 --count;
522 if (count == 0) {
523 rc = -EINVAL;
Tomasz Stanislawski470043b2013-06-06 09:30:50 +0200524 goto out;
Rafal Krypa10289b02013-08-09 11:47:07 +0200525 }
526 }
527
528 data[count] = '\0';
529 tokens = (format == SMK_CHANGE_FMT ? 4 : 3);
530 while (cnt < count) {
531 if (format == SMK_FIXED24_FMT) {
532 rc = smk_parse_rule(data, &rule, 1);
533 if (rc != 0) {
534 rc = -EINVAL;
535 goto out;
536 }
537 cnt = count;
538 } else {
539 rc = smk_parse_long_rule(data + cnt, &rule, 1, tokens);
540 if (rc <= 0) {
541 rc = -EINVAL;
542 goto out;
543 }
544 cnt += rc;
545 }
546
547 if (rule_list == NULL)
548 rc = smk_set_access(&rule, &rule.smk_subject->smk_rules,
549 &rule.smk_subject->smk_rules_lock, 1);
550 else
551 rc = smk_set_access(&rule, rule_list, rule_lock, 0);
552
553 if (rc)
Tomasz Stanislawski470043b2013-06-06 09:30:50 +0200554 goto out;
Casey Schauflerf7112e62012-05-06 15:22:02 -0700555 }
556
Rafal Krypa10289b02013-08-09 11:47:07 +0200557 rc = cnt;
Casey Schauflere114e472008-02-04 22:29:50 -0800558out:
559 kfree(data);
560 return rc;
561}
562
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800563/*
Casey Schaufler40809562011-11-10 15:02:22 -0800564 * Core logic for smackfs seq list operations.
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800565 */
566
Casey Schaufler40809562011-11-10 15:02:22 -0800567static void *smk_seq_start(struct seq_file *s, loff_t *pos,
568 struct list_head *head)
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800569{
Casey Schaufler272cd7a2011-09-20 12:24:36 -0700570 struct list_head *list;
571
572 /*
573 * This is 0 the first time through.
574 */
575 if (s->index == 0)
Casey Schaufler40809562011-11-10 15:02:22 -0800576 s->private = head;
Casey Schaufler272cd7a2011-09-20 12:24:36 -0700577
578 if (s->private == NULL)
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800579 return NULL;
Casey Schaufler272cd7a2011-09-20 12:24:36 -0700580
581 list = s->private;
582 if (list_empty(list))
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800583 return NULL;
Casey Schaufler272cd7a2011-09-20 12:24:36 -0700584
585 if (s->index == 0)
586 return list->next;
587 return list;
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800588}
589
Casey Schaufler40809562011-11-10 15:02:22 -0800590static void *smk_seq_next(struct seq_file *s, void *v, loff_t *pos,
591 struct list_head *head)
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800592{
593 struct list_head *list = v;
594
Casey Schaufler40809562011-11-10 15:02:22 -0800595 if (list_is_last(list, head)) {
Casey Schaufler272cd7a2011-09-20 12:24:36 -0700596 s->private = NULL;
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800597 return NULL;
598 }
Casey Schaufler272cd7a2011-09-20 12:24:36 -0700599 s->private = list->next;
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800600 return list->next;
601}
602
Casey Schaufler40809562011-11-10 15:02:22 -0800603static void smk_seq_stop(struct seq_file *s, void *v)
604{
605 /* No-op */
606}
607
Casey Schauflerf7112e62012-05-06 15:22:02 -0700608static void smk_rule_show(struct seq_file *s, struct smack_rule *srp, int max)
Casey Schaufler40809562011-11-10 15:02:22 -0800609{
Casey Schauflerf7112e62012-05-06 15:22:02 -0700610 /*
611 * Don't show any rules with label names too long for
612 * interface file (/smack/load or /smack/load2)
613 * because you should expect to be able to write
614 * anything you read back.
615 */
Casey Schaufler2f823ff2013-05-22 18:43:03 -0700616 if (strlen(srp->smk_subject->smk_known) >= max ||
Lukasz Pawelczyk21c7eae2014-08-29 17:02:55 +0200617 strlen(srp->smk_object->smk_known) >= max)
Casey Schauflerf7112e62012-05-06 15:22:02 -0700618 return;
Casey Schaufler40809562011-11-10 15:02:22 -0800619
Rafal Krypa65ee7f42012-07-09 19:36:34 +0200620 if (srp->smk_access == 0)
621 return;
622
Lukasz Pawelczyk21c7eae2014-08-29 17:02:55 +0200623 seq_printf(s, "%s %s",
624 srp->smk_subject->smk_known,
625 srp->smk_object->smk_known);
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800626
627 seq_putc(s, ' ');
628
629 if (srp->smk_access & MAY_READ)
630 seq_putc(s, 'r');
631 if (srp->smk_access & MAY_WRITE)
632 seq_putc(s, 'w');
633 if (srp->smk_access & MAY_EXEC)
634 seq_putc(s, 'x');
635 if (srp->smk_access & MAY_APPEND)
636 seq_putc(s, 'a');
637 if (srp->smk_access & MAY_TRANSMUTE)
638 seq_putc(s, 't');
Casey Schauflerc0ab6e52013-10-11 18:06:39 -0700639 if (srp->smk_access & MAY_LOCK)
640 seq_putc(s, 'l');
Casey Schauflerd166c802014-08-27 14:51:27 -0700641 if (srp->smk_access & MAY_BRINGUP)
642 seq_putc(s, 'b');
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800643
644 seq_putc(s, '\n');
Casey Schauflerf7112e62012-05-06 15:22:02 -0700645}
646
647/*
648 * Seq_file read operations for /smack/load
649 */
650
651static void *load2_seq_start(struct seq_file *s, loff_t *pos)
652{
653 return smk_seq_start(s, pos, &smack_rule_list);
654}
655
656static void *load2_seq_next(struct seq_file *s, void *v, loff_t *pos)
657{
658 return smk_seq_next(s, v, pos, &smack_rule_list);
659}
660
661static int load_seq_show(struct seq_file *s, void *v)
662{
663 struct list_head *list = v;
664 struct smack_master_list *smlp =
665 list_entry(list, struct smack_master_list, list);
666
667 smk_rule_show(s, smlp->smk_rule, SMK_LABELLEN);
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800668
669 return 0;
670}
671
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800672static const struct seq_operations load_seq_ops = {
Casey Schauflerf7112e62012-05-06 15:22:02 -0700673 .start = load2_seq_start,
674 .next = load2_seq_next,
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800675 .show = load_seq_show,
Casey Schaufler40809562011-11-10 15:02:22 -0800676 .stop = smk_seq_stop,
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800677};
678
679/**
680 * smk_open_load - open() for /smack/load
681 * @inode: inode structure representing file
682 * @file: "load" file pointer
683 *
684 * For reading, use load_seq_* seq_file reading operations.
685 */
686static int smk_open_load(struct inode *inode, struct file *file)
687{
688 return seq_open(file, &load_seq_ops);
689}
690
691/**
692 * smk_write_load - write() for /smack/load
693 * @file: file pointer, not actually used
694 * @buf: where to get the data from
695 * @count: bytes sent
696 * @ppos: where to start - must be 0
697 *
698 */
699static ssize_t smk_write_load(struct file *file, const char __user *buf,
700 size_t count, loff_t *ppos)
701{
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800702 /*
703 * Must have privilege.
704 * No partial writes.
705 * Enough data must be present.
706 */
Casey Schaufler1880eff2012-06-05 15:28:30 -0700707 if (!smack_privileged(CAP_MAC_ADMIN))
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800708 return -EPERM;
709
Casey Schauflerf7112e62012-05-06 15:22:02 -0700710 return smk_write_rules_list(file, buf, count, ppos, NULL, NULL,
711 SMK_FIXED24_FMT);
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800712}
713
Casey Schauflere114e472008-02-04 22:29:50 -0800714static const struct file_operations smk_load_ops = {
715 .open = smk_open_load,
716 .read = seq_read,
717 .llseek = seq_lseek,
718 .write = smk_write_load,
Ahmed S. Darwishcb622bb2008-03-24 12:29:49 -0700719 .release = seq_release,
Casey Schauflere114e472008-02-04 22:29:50 -0800720};
721
722/**
723 * smk_cipso_doi - initialize the CIPSO domain
724 */
Casey Schaufler30aa4fa2008-04-28 02:13:43 -0700725static void smk_cipso_doi(void)
Casey Schauflere114e472008-02-04 22:29:50 -0800726{
727 int rc;
728 struct cipso_v4_doi *doip;
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500729 struct netlbl_audit nai;
Casey Schauflere114e472008-02-04 22:29:50 -0800730
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500731 smk_netlabel_audit_set(&nai);
Casey Schaufler4bc87e62008-02-15 15:24:25 -0800732
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500733 rc = netlbl_cfg_map_del(NULL, PF_INET, NULL, NULL, &nai);
Casey Schauflere114e472008-02-04 22:29:50 -0800734 if (rc != 0)
735 printk(KERN_WARNING "%s:%d remove rc = %d\n",
736 __func__, __LINE__, rc);
737
738 doip = kmalloc(sizeof(struct cipso_v4_doi), GFP_KERNEL);
739 if (doip == NULL)
740 panic("smack: Failed to initialize cipso DOI.\n");
741 doip->map.std = NULL;
742 doip->doi = smk_cipso_doi_value;
743 doip->type = CIPSO_V4_MAP_PASS;
744 doip->tags[0] = CIPSO_V4_TAG_RBITMAP;
745 for (rc = 1; rc < CIPSO_V4_TAG_MAXCNT; rc++)
746 doip->tags[rc] = CIPSO_V4_TAG_INVALID;
747
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500748 rc = netlbl_cfg_cipsov4_add(doip, &nai);
Paul Mooreb1edeb12008-10-10 10:16:31 -0400749 if (rc != 0) {
Paul Moore6c2e8ac2008-12-31 12:54:11 -0500750 printk(KERN_WARNING "%s:%d cipso add rc = %d\n",
Casey Schauflere114e472008-02-04 22:29:50 -0800751 __func__, __LINE__, rc);
Paul Mooreb1edeb12008-10-10 10:16:31 -0400752 kfree(doip);
Paul Moore6c2e8ac2008-12-31 12:54:11 -0500753 return;
754 }
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500755 rc = netlbl_cfg_cipsov4_map_add(doip->doi, NULL, NULL, NULL, &nai);
Paul Moore6c2e8ac2008-12-31 12:54:11 -0500756 if (rc != 0) {
757 printk(KERN_WARNING "%s:%d map add rc = %d\n",
758 __func__, __LINE__, rc);
759 kfree(doip);
760 return;
Paul Mooreb1edeb12008-10-10 10:16:31 -0400761 }
Casey Schauflere114e472008-02-04 22:29:50 -0800762}
763
Casey Schaufler4bc87e62008-02-15 15:24:25 -0800764/**
765 * smk_unlbl_ambient - initialize the unlabeled domain
Randy Dunlap251a2a92009-02-18 11:42:33 -0800766 * @oldambient: previous domain string
Casey Schaufler4bc87e62008-02-15 15:24:25 -0800767 */
Casey Schaufler30aa4fa2008-04-28 02:13:43 -0700768static void smk_unlbl_ambient(char *oldambient)
Casey Schaufler4bc87e62008-02-15 15:24:25 -0800769{
770 int rc;
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500771 struct netlbl_audit nai;
Casey Schaufler4bc87e62008-02-15 15:24:25 -0800772
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500773 smk_netlabel_audit_set(&nai);
Casey Schaufler4bc87e62008-02-15 15:24:25 -0800774
775 if (oldambient != NULL) {
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500776 rc = netlbl_cfg_map_del(oldambient, PF_INET, NULL, NULL, &nai);
Casey Schaufler4bc87e62008-02-15 15:24:25 -0800777 if (rc != 0)
778 printk(KERN_WARNING "%s:%d remove rc = %d\n",
779 __func__, __LINE__, rc);
780 }
Casey Schauflerf7112e62012-05-06 15:22:02 -0700781 if (smack_net_ambient == NULL)
Casey Schaufler2f823ff2013-05-22 18:43:03 -0700782 smack_net_ambient = &smack_known_floor;
Casey Schaufler4bc87e62008-02-15 15:24:25 -0800783
Casey Schaufler2f823ff2013-05-22 18:43:03 -0700784 rc = netlbl_cfg_unlbl_map_add(smack_net_ambient->smk_known, PF_INET,
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500785 NULL, NULL, &nai);
Casey Schaufler4bc87e62008-02-15 15:24:25 -0800786 if (rc != 0)
787 printk(KERN_WARNING "%s:%d add rc = %d\n",
788 __func__, __LINE__, rc);
789}
790
Casey Schauflere114e472008-02-04 22:29:50 -0800791/*
792 * Seq_file read operations for /smack/cipso
793 */
794
795static void *cipso_seq_start(struct seq_file *s, loff_t *pos)
796{
Casey Schaufler40809562011-11-10 15:02:22 -0800797 return smk_seq_start(s, pos, &smack_known_list);
Casey Schauflere114e472008-02-04 22:29:50 -0800798}
799
800static void *cipso_seq_next(struct seq_file *s, void *v, loff_t *pos)
801{
Casey Schaufler40809562011-11-10 15:02:22 -0800802 return smk_seq_next(s, v, pos, &smack_known_list);
Casey Schauflere114e472008-02-04 22:29:50 -0800803}
804
805/*
806 * Print cipso labels in format:
807 * label level[/cat[,cat]]
808 */
809static int cipso_seq_show(struct seq_file *s, void *v)
810{
Etienne Basset7198e2e2009-03-24 20:53:24 +0100811 struct list_head *list = v;
812 struct smack_known *skp =
813 list_entry(list, struct smack_known, list);
Paul Moore4fbe63d2014-08-01 11:17:37 -0400814 struct netlbl_lsm_catmap *cmp = skp->smk_netlabel.attr.mls.cat;
Casey Schauflere114e472008-02-04 22:29:50 -0800815 char sep = '/';
Casey Schauflere114e472008-02-04 22:29:50 -0800816 int i;
Casey Schauflere114e472008-02-04 22:29:50 -0800817
Casey Schauflerf7112e62012-05-06 15:22:02 -0700818 /*
819 * Don't show a label that could not have been set using
820 * /smack/cipso. This is in support of the notion that
821 * anything read from /smack/cipso ought to be writeable
822 * to /smack/cipso.
823 *
824 * /smack/cipso2 should be used instead.
825 */
826 if (strlen(skp->smk_known) >= SMK_LABELLEN)
Casey Schauflere114e472008-02-04 22:29:50 -0800827 return 0;
828
Casey Schauflerf7112e62012-05-06 15:22:02 -0700829 seq_printf(s, "%s %3d", skp->smk_known, skp->smk_netlabel.attr.mls.lvl);
Casey Schauflere114e472008-02-04 22:29:50 -0800830
Paul Moore4fbe63d2014-08-01 11:17:37 -0400831 for (i = netlbl_catmap_walk(cmp, 0); i >= 0;
832 i = netlbl_catmap_walk(cmp, i + 1)) {
Casey Schauflerf7112e62012-05-06 15:22:02 -0700833 seq_printf(s, "%c%d", sep, i);
834 sep = ',';
835 }
Casey Schauflere114e472008-02-04 22:29:50 -0800836
837 seq_putc(s, '\n');
838
839 return 0;
840}
841
James Morris88e9d342009-09-22 16:43:43 -0700842static const struct seq_operations cipso_seq_ops = {
Casey Schauflere114e472008-02-04 22:29:50 -0800843 .start = cipso_seq_start,
Casey Schauflere114e472008-02-04 22:29:50 -0800844 .next = cipso_seq_next,
845 .show = cipso_seq_show,
Casey Schaufler40809562011-11-10 15:02:22 -0800846 .stop = smk_seq_stop,
Casey Schauflere114e472008-02-04 22:29:50 -0800847};
848
849/**
850 * smk_open_cipso - open() for /smack/cipso
851 * @inode: inode structure representing file
852 * @file: "cipso" file pointer
853 *
854 * Connect our cipso_seq_* operations with /smack/cipso
855 * file_operations
856 */
857static int smk_open_cipso(struct inode *inode, struct file *file)
858{
859 return seq_open(file, &cipso_seq_ops);
860}
861
862/**
Casey Schauflerf7112e62012-05-06 15:22:02 -0700863 * smk_set_cipso - do the work for write() for cipso and cipso2
Randy Dunlap251a2a92009-02-18 11:42:33 -0800864 * @file: file pointer, not actually used
Casey Schauflere114e472008-02-04 22:29:50 -0800865 * @buf: where to get the data from
866 * @count: bytes sent
867 * @ppos: where to start
Casey Schauflerf7112e62012-05-06 15:22:02 -0700868 * @format: /smack/cipso or /smack/cipso2
Casey Schauflere114e472008-02-04 22:29:50 -0800869 *
870 * Accepts only one cipso rule per write call.
871 * Returns number of bytes written or error code, as appropriate
872 */
Casey Schauflerf7112e62012-05-06 15:22:02 -0700873static ssize_t smk_set_cipso(struct file *file, const char __user *buf,
874 size_t count, loff_t *ppos, int format)
Casey Schauflere114e472008-02-04 22:29:50 -0800875{
876 struct smack_known *skp;
Casey Schauflerf7112e62012-05-06 15:22:02 -0700877 struct netlbl_lsm_secattr ncats;
878 char mapcatset[SMK_CIPSOLEN];
Casey Schauflere114e472008-02-04 22:29:50 -0800879 int maplevel;
Casey Schauflerf7112e62012-05-06 15:22:02 -0700880 unsigned int cat;
Casey Schauflere114e472008-02-04 22:29:50 -0800881 int catlen;
882 ssize_t rc = -EINVAL;
883 char *data = NULL;
884 char *rule;
885 int ret;
886 int i;
887
888 /*
889 * Must have privilege.
890 * No partial writes.
891 * Enough data must be present.
892 */
Casey Schaufler1880eff2012-06-05 15:28:30 -0700893 if (!smack_privileged(CAP_MAC_ADMIN))
Casey Schauflere114e472008-02-04 22:29:50 -0800894 return -EPERM;
895 if (*ppos != 0)
896 return -EINVAL;
Casey Schauflerf7112e62012-05-06 15:22:02 -0700897 if (format == SMK_FIXED24_FMT &&
898 (count < SMK_CIPSOMIN || count > SMK_CIPSOMAX))
Casey Schauflere114e472008-02-04 22:29:50 -0800899 return -EINVAL;
900
901 data = kzalloc(count + 1, GFP_KERNEL);
902 if (data == NULL)
903 return -ENOMEM;
904
905 if (copy_from_user(data, buf, count) != 0) {
906 rc = -EFAULT;
907 goto unlockedout;
908 }
909
910 data[count] = '\0';
911 rule = data;
912 /*
913 * Only allow one writer at a time. Writes should be
914 * quite rare and small in any case.
915 */
916 mutex_lock(&smack_cipso_lock);
917
918 skp = smk_import_entry(rule, 0);
919 if (skp == NULL)
920 goto out;
921
Casey Schauflerf7112e62012-05-06 15:22:02 -0700922 if (format == SMK_FIXED24_FMT)
923 rule += SMK_LABELLEN;
924 else
Passion,Zhao0fcfee62013-06-03 11:42:24 +0800925 rule += strlen(skp->smk_known) + 1;
Casey Schauflerf7112e62012-05-06 15:22:02 -0700926
Casey Schauflere114e472008-02-04 22:29:50 -0800927 ret = sscanf(rule, "%d", &maplevel);
928 if (ret != 1 || maplevel > SMACK_CIPSO_MAXLEVEL)
929 goto out;
930
931 rule += SMK_DIGITLEN;
932 ret = sscanf(rule, "%d", &catlen);
933 if (ret != 1 || catlen > SMACK_CIPSO_MAXCATNUM)
934 goto out;
935
Casey Schauflerf7112e62012-05-06 15:22:02 -0700936 if (format == SMK_FIXED24_FMT &&
937 count != (SMK_CIPSOMIN + catlen * SMK_DIGITLEN))
Casey Schauflere114e472008-02-04 22:29:50 -0800938 goto out;
939
940 memset(mapcatset, 0, sizeof(mapcatset));
941
942 for (i = 0; i < catlen; i++) {
943 rule += SMK_DIGITLEN;
Casey Schauflerf7112e62012-05-06 15:22:02 -0700944 ret = sscanf(rule, "%u", &cat);
Casey Schaufler677264e2013-06-28 13:47:07 -0700945 if (ret != 1 || cat > SMACK_CIPSO_MAXCATNUM)
Casey Schauflere114e472008-02-04 22:29:50 -0800946 goto out;
947
948 smack_catset_bit(cat, mapcatset);
949 }
950
Casey Schauflerf7112e62012-05-06 15:22:02 -0700951 rc = smk_netlbl_mls(maplevel, mapcatset, &ncats, SMK_CIPSOLEN);
952 if (rc >= 0) {
Paul Moore4fbe63d2014-08-01 11:17:37 -0400953 netlbl_catmap_free(skp->smk_netlabel.attr.mls.cat);
Casey Schauflerf7112e62012-05-06 15:22:02 -0700954 skp->smk_netlabel.attr.mls.cat = ncats.attr.mls.cat;
955 skp->smk_netlabel.attr.mls.lvl = ncats.attr.mls.lvl;
956 rc = count;
Casey Schauflere114e472008-02-04 22:29:50 -0800957 }
958
Casey Schauflere114e472008-02-04 22:29:50 -0800959out:
960 mutex_unlock(&smack_cipso_lock);
961unlockedout:
962 kfree(data);
963 return rc;
964}
965
Casey Schauflerf7112e62012-05-06 15:22:02 -0700966/**
967 * smk_write_cipso - write() for /smack/cipso
968 * @file: file pointer, not actually used
969 * @buf: where to get the data from
970 * @count: bytes sent
971 * @ppos: where to start
972 *
973 * Accepts only one cipso rule per write call.
974 * Returns number of bytes written or error code, as appropriate
975 */
976static ssize_t smk_write_cipso(struct file *file, const char __user *buf,
977 size_t count, loff_t *ppos)
978{
979 return smk_set_cipso(file, buf, count, ppos, SMK_FIXED24_FMT);
980}
981
Casey Schauflere114e472008-02-04 22:29:50 -0800982static const struct file_operations smk_cipso_ops = {
983 .open = smk_open_cipso,
984 .read = seq_read,
985 .llseek = seq_lseek,
986 .write = smk_write_cipso,
987 .release = seq_release,
988};
989
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500990/*
Casey Schauflerf7112e62012-05-06 15:22:02 -0700991 * Seq_file read operations for /smack/cipso2
992 */
993
994/*
995 * Print cipso labels in format:
996 * label level[/cat[,cat]]
997 */
998static int cipso2_seq_show(struct seq_file *s, void *v)
999{
1000 struct list_head *list = v;
1001 struct smack_known *skp =
1002 list_entry(list, struct smack_known, list);
Paul Moore4fbe63d2014-08-01 11:17:37 -04001003 struct netlbl_lsm_catmap *cmp = skp->smk_netlabel.attr.mls.cat;
Casey Schauflerf7112e62012-05-06 15:22:02 -07001004 char sep = '/';
1005 int i;
1006
1007 seq_printf(s, "%s %3d", skp->smk_known, skp->smk_netlabel.attr.mls.lvl);
1008
Paul Moore4fbe63d2014-08-01 11:17:37 -04001009 for (i = netlbl_catmap_walk(cmp, 0); i >= 0;
1010 i = netlbl_catmap_walk(cmp, i + 1)) {
Casey Schauflerf7112e62012-05-06 15:22:02 -07001011 seq_printf(s, "%c%d", sep, i);
1012 sep = ',';
1013 }
1014
1015 seq_putc(s, '\n');
1016
1017 return 0;
1018}
1019
1020static const struct seq_operations cipso2_seq_ops = {
1021 .start = cipso_seq_start,
1022 .next = cipso_seq_next,
1023 .show = cipso2_seq_show,
1024 .stop = smk_seq_stop,
1025};
1026
1027/**
1028 * smk_open_cipso2 - open() for /smack/cipso2
1029 * @inode: inode structure representing file
1030 * @file: "cipso2" file pointer
1031 *
1032 * Connect our cipso_seq_* operations with /smack/cipso2
1033 * file_operations
1034 */
1035static int smk_open_cipso2(struct inode *inode, struct file *file)
1036{
1037 return seq_open(file, &cipso2_seq_ops);
1038}
1039
1040/**
1041 * smk_write_cipso2 - write() for /smack/cipso2
1042 * @file: file pointer, not actually used
1043 * @buf: where to get the data from
1044 * @count: bytes sent
1045 * @ppos: where to start
1046 *
1047 * Accepts only one cipso rule per write call.
1048 * Returns number of bytes written or error code, as appropriate
1049 */
1050static ssize_t smk_write_cipso2(struct file *file, const char __user *buf,
1051 size_t count, loff_t *ppos)
1052{
1053 return smk_set_cipso(file, buf, count, ppos, SMK_LONG_FMT);
1054}
1055
1056static const struct file_operations smk_cipso2_ops = {
1057 .open = smk_open_cipso2,
1058 .read = seq_read,
1059 .llseek = seq_lseek,
1060 .write = smk_write_cipso2,
1061 .release = seq_release,
1062};
1063
1064/*
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001065 * Seq_file read operations for /smack/netlabel
1066 */
1067
1068static void *netlbladdr_seq_start(struct seq_file *s, loff_t *pos)
1069{
Casey Schaufler40809562011-11-10 15:02:22 -08001070 return smk_seq_start(s, pos, &smk_netlbladdr_list);
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001071}
1072
1073static void *netlbladdr_seq_next(struct seq_file *s, void *v, loff_t *pos)
1074{
Casey Schaufler40809562011-11-10 15:02:22 -08001075 return smk_seq_next(s, v, pos, &smk_netlbladdr_list);
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001076}
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001077#define BEBITS (sizeof(__be32) * 8)
1078
1079/*
1080 * Print host/label pairs
1081 */
1082static int netlbladdr_seq_show(struct seq_file *s, void *v)
1083{
Etienne Basset7198e2e2009-03-24 20:53:24 +01001084 struct list_head *list = v;
1085 struct smk_netlbladdr *skp =
1086 list_entry(list, struct smk_netlbladdr, list);
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001087 unsigned char *hp = (char *) &skp->smk_host.sin_addr.s_addr;
etienne113a0e42009-03-04 07:33:51 +01001088 int maskn;
1089 u32 temp_mask = be32_to_cpu(skp->smk_mask.s_addr);
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001090
etienne113a0e42009-03-04 07:33:51 +01001091 for (maskn = 0; temp_mask; temp_mask <<= 1, maskn++);
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001092
1093 seq_printf(s, "%u.%u.%u.%u/%d %s\n",
Lukasz Pawelczyk21c7eae2014-08-29 17:02:55 +02001094 hp[0], hp[1], hp[2], hp[3], maskn, skp->smk_label->smk_known);
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001095
1096 return 0;
1097}
1098
James Morris88e9d342009-09-22 16:43:43 -07001099static const struct seq_operations netlbladdr_seq_ops = {
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001100 .start = netlbladdr_seq_start,
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001101 .next = netlbladdr_seq_next,
1102 .show = netlbladdr_seq_show,
Casey Schaufler40809562011-11-10 15:02:22 -08001103 .stop = smk_seq_stop,
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001104};
1105
1106/**
1107 * smk_open_netlbladdr - open() for /smack/netlabel
1108 * @inode: inode structure representing file
1109 * @file: "netlabel" file pointer
1110 *
1111 * Connect our netlbladdr_seq_* operations with /smack/netlabel
1112 * file_operations
1113 */
1114static int smk_open_netlbladdr(struct inode *inode, struct file *file)
1115{
1116 return seq_open(file, &netlbladdr_seq_ops);
1117}
1118
1119/**
etienne113a0e42009-03-04 07:33:51 +01001120 * smk_netlbladdr_insert
1121 * @new : netlabel to insert
1122 *
1123 * This helper insert netlabel in the smack_netlbladdrs list
1124 * sorted by netmask length (longest to smallest)
Etienne Basset7198e2e2009-03-24 20:53:24 +01001125 * locked by &smk_netlbladdr_lock in smk_write_netlbladdr
1126 *
etienne113a0e42009-03-04 07:33:51 +01001127 */
1128static void smk_netlbladdr_insert(struct smk_netlbladdr *new)
1129{
Etienne Basset7198e2e2009-03-24 20:53:24 +01001130 struct smk_netlbladdr *m, *m_next;
etienne113a0e42009-03-04 07:33:51 +01001131
Etienne Basset7198e2e2009-03-24 20:53:24 +01001132 if (list_empty(&smk_netlbladdr_list)) {
1133 list_add_rcu(&new->list, &smk_netlbladdr_list);
etienne113a0e42009-03-04 07:33:51 +01001134 return;
1135 }
1136
Jiri Pirko05725f72009-04-14 20:17:16 +02001137 m = list_entry_rcu(smk_netlbladdr_list.next,
1138 struct smk_netlbladdr, list);
Etienne Basset7198e2e2009-03-24 20:53:24 +01001139
etienne113a0e42009-03-04 07:33:51 +01001140 /* the comparison '>' is a bit hacky, but works */
Etienne Basset7198e2e2009-03-24 20:53:24 +01001141 if (new->smk_mask.s_addr > m->smk_mask.s_addr) {
1142 list_add_rcu(&new->list, &smk_netlbladdr_list);
etienne113a0e42009-03-04 07:33:51 +01001143 return;
1144 }
Etienne Basset7198e2e2009-03-24 20:53:24 +01001145
1146 list_for_each_entry_rcu(m, &smk_netlbladdr_list, list) {
1147 if (list_is_last(&m->list, &smk_netlbladdr_list)) {
1148 list_add_rcu(&new->list, &m->list);
etienne113a0e42009-03-04 07:33:51 +01001149 return;
1150 }
Jiri Pirko05725f72009-04-14 20:17:16 +02001151 m_next = list_entry_rcu(m->list.next,
1152 struct smk_netlbladdr, list);
Etienne Basset7198e2e2009-03-24 20:53:24 +01001153 if (new->smk_mask.s_addr > m_next->smk_mask.s_addr) {
1154 list_add_rcu(&new->list, &m->list);
etienne113a0e42009-03-04 07:33:51 +01001155 return;
1156 }
1157 }
1158}
1159
1160
1161/**
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001162 * smk_write_netlbladdr - write() for /smack/netlabel
Randy Dunlap251a2a92009-02-18 11:42:33 -08001163 * @file: file pointer, not actually used
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001164 * @buf: where to get the data from
1165 * @count: bytes sent
1166 * @ppos: where to start
1167 *
1168 * Accepts only one netlbladdr per write call.
1169 * Returns number of bytes written or error code, as appropriate
1170 */
1171static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
1172 size_t count, loff_t *ppos)
1173{
Lukasz Pawelczyk21c7eae2014-08-29 17:02:55 +02001174 struct smk_netlbladdr *snp;
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001175 struct sockaddr_in newname;
Casey Schauflerf7112e62012-05-06 15:22:02 -07001176 char *smack;
Lukasz Pawelczyk21c7eae2014-08-29 17:02:55 +02001177 struct smack_known *skp;
Casey Schauflerf7112e62012-05-06 15:22:02 -07001178 char *data;
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001179 char *host = (char *)&newname.sin_addr.s_addr;
1180 int rc;
1181 struct netlbl_audit audit_info;
1182 struct in_addr mask;
1183 unsigned int m;
Etienne Basset7198e2e2009-03-24 20:53:24 +01001184 int found;
etienne113a0e42009-03-04 07:33:51 +01001185 u32 mask_bits = (1<<31);
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001186 __be32 nsa;
etienne113a0e42009-03-04 07:33:51 +01001187 u32 temp_mask;
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001188
1189 /*
1190 * Must have privilege.
1191 * No partial writes.
1192 * Enough data must be present.
1193 * "<addr/mask, as a.b.c.d/e><space><label>"
1194 * "<addr, as a.b.c.d><space><label>"
1195 */
Casey Schaufler1880eff2012-06-05 15:28:30 -07001196 if (!smack_privileged(CAP_MAC_ADMIN))
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001197 return -EPERM;
1198 if (*ppos != 0)
1199 return -EINVAL;
Casey Schauflerf7112e62012-05-06 15:22:02 -07001200 if (count < SMK_NETLBLADDRMIN)
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001201 return -EINVAL;
Casey Schauflerf7112e62012-05-06 15:22:02 -07001202
1203 data = kzalloc(count + 1, GFP_KERNEL);
1204 if (data == NULL)
1205 return -ENOMEM;
1206
1207 if (copy_from_user(data, buf, count) != 0) {
1208 rc = -EFAULT;
1209 goto free_data_out;
1210 }
1211
1212 smack = kzalloc(count + 1, GFP_KERNEL);
1213 if (smack == NULL) {
1214 rc = -ENOMEM;
1215 goto free_data_out;
1216 }
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001217
1218 data[count] = '\0';
1219
Toralf Försterec554fa2014-04-27 19:33:34 +02001220 rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd/%u %s",
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001221 &host[0], &host[1], &host[2], &host[3], &m, smack);
1222 if (rc != 6) {
1223 rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd %s",
1224 &host[0], &host[1], &host[2], &host[3], smack);
Casey Schauflerf7112e62012-05-06 15:22:02 -07001225 if (rc != 5) {
1226 rc = -EINVAL;
1227 goto free_out;
1228 }
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001229 m = BEBITS;
1230 }
Casey Schauflerf7112e62012-05-06 15:22:02 -07001231 if (m > BEBITS) {
1232 rc = -EINVAL;
1233 goto free_out;
1234 }
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001235
Casey Schauflerf7112e62012-05-06 15:22:02 -07001236 /*
1237 * If smack begins with '-', it is an option, don't import it
1238 */
Etienne Basset43031542009-03-27 17:11:01 -04001239 if (smack[0] != '-') {
Lukasz Pawelczyk21c7eae2014-08-29 17:02:55 +02001240 skp = smk_import_entry(smack, 0);
1241 if (skp == NULL) {
Casey Schauflerf7112e62012-05-06 15:22:02 -07001242 rc = -EINVAL;
1243 goto free_out;
1244 }
Etienne Basset43031542009-03-27 17:11:01 -04001245 } else {
1246 /* check known options */
Lukasz Pawelczyk21c7eae2014-08-29 17:02:55 +02001247 if (strcmp(smack, smack_cipso_option.smk_known) == 0)
1248 skp = &smack_cipso_option;
Casey Schauflerf7112e62012-05-06 15:22:02 -07001249 else {
1250 rc = -EINVAL;
1251 goto free_out;
1252 }
Etienne Basset43031542009-03-27 17:11:01 -04001253 }
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001254
etienne113a0e42009-03-04 07:33:51 +01001255 for (temp_mask = 0; m > 0; m--) {
1256 temp_mask |= mask_bits;
1257 mask_bits >>= 1;
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001258 }
etienne113a0e42009-03-04 07:33:51 +01001259 mask.s_addr = cpu_to_be32(temp_mask);
1260
1261 newname.sin_addr.s_addr &= mask.s_addr;
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001262 /*
1263 * Only allow one writer at a time. Writes should be
1264 * quite rare and small in any case.
1265 */
1266 mutex_lock(&smk_netlbladdr_lock);
1267
1268 nsa = newname.sin_addr.s_addr;
etienne113a0e42009-03-04 07:33:51 +01001269 /* try to find if the prefix is already in the list */
Etienne Basset7198e2e2009-03-24 20:53:24 +01001270 found = 0;
Lukasz Pawelczyk21c7eae2014-08-29 17:02:55 +02001271 list_for_each_entry_rcu(snp, &smk_netlbladdr_list, list) {
1272 if (snp->smk_host.sin_addr.s_addr == nsa &&
1273 snp->smk_mask.s_addr == mask.s_addr) {
Etienne Basset7198e2e2009-03-24 20:53:24 +01001274 found = 1;
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001275 break;
Etienne Basset7198e2e2009-03-24 20:53:24 +01001276 }
1277 }
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001278 smk_netlabel_audit_set(&audit_info);
1279
Etienne Basset7198e2e2009-03-24 20:53:24 +01001280 if (found == 0) {
Lukasz Pawelczyk21c7eae2014-08-29 17:02:55 +02001281 snp = kzalloc(sizeof(*snp), GFP_KERNEL);
1282 if (snp == NULL)
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001283 rc = -ENOMEM;
1284 else {
1285 rc = 0;
Lukasz Pawelczyk21c7eae2014-08-29 17:02:55 +02001286 snp->smk_host.sin_addr.s_addr = newname.sin_addr.s_addr;
1287 snp->smk_mask.s_addr = mask.s_addr;
1288 snp->smk_label = skp;
1289 smk_netlbladdr_insert(snp);
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001290 }
1291 } else {
Etienne Basset43031542009-03-27 17:11:01 -04001292 /* we delete the unlabeled entry, only if the previous label
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001293 * wasn't the special CIPSO option */
Lukasz Pawelczyk21c7eae2014-08-29 17:02:55 +02001294 if (snp->smk_label != &smack_cipso_option)
Etienne Basset43031542009-03-27 17:11:01 -04001295 rc = netlbl_cfg_unlbl_static_del(&init_net, NULL,
Lukasz Pawelczyk21c7eae2014-08-29 17:02:55 +02001296 &snp->smk_host.sin_addr, &snp->smk_mask,
Etienne Basset43031542009-03-27 17:11:01 -04001297 PF_INET, &audit_info);
1298 else
1299 rc = 0;
Lukasz Pawelczyk21c7eae2014-08-29 17:02:55 +02001300 snp->smk_label = skp;
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001301 }
1302
1303 /*
1304 * Now tell netlabel about the single label nature of
1305 * this host so that incoming packets get labeled.
Etienne Basset43031542009-03-27 17:11:01 -04001306 * but only if we didn't get the special CIPSO option
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001307 */
Lukasz Pawelczyk21c7eae2014-08-29 17:02:55 +02001308 if (rc == 0 && skp != &smack_cipso_option)
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001309 rc = netlbl_cfg_unlbl_static_add(&init_net, NULL,
Lukasz Pawelczyk21c7eae2014-08-29 17:02:55 +02001310 &snp->smk_host.sin_addr, &snp->smk_mask, PF_INET,
1311 snp->smk_label->smk_secid, &audit_info);
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001312
1313 if (rc == 0)
1314 rc = count;
1315
1316 mutex_unlock(&smk_netlbladdr_lock);
1317
Casey Schauflerf7112e62012-05-06 15:22:02 -07001318free_out:
1319 kfree(smack);
1320free_data_out:
1321 kfree(data);
1322
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001323 return rc;
1324}
1325
1326static const struct file_operations smk_netlbladdr_ops = {
1327 .open = smk_open_netlbladdr,
1328 .read = seq_read,
1329 .llseek = seq_lseek,
1330 .write = smk_write_netlbladdr,
1331 .release = seq_release,
1332};
1333
Casey Schauflere114e472008-02-04 22:29:50 -08001334/**
1335 * smk_read_doi - read() for /smack/doi
1336 * @filp: file pointer, not actually used
1337 * @buf: where to put the result
1338 * @count: maximum to send along
1339 * @ppos: where to start
1340 *
1341 * Returns number of bytes read or error code, as appropriate
1342 */
1343static ssize_t smk_read_doi(struct file *filp, char __user *buf,
1344 size_t count, loff_t *ppos)
1345{
1346 char temp[80];
1347 ssize_t rc;
1348
1349 if (*ppos != 0)
1350 return 0;
1351
1352 sprintf(temp, "%d", smk_cipso_doi_value);
1353 rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
1354
1355 return rc;
1356}
1357
1358/**
1359 * smk_write_doi - write() for /smack/doi
Randy Dunlap251a2a92009-02-18 11:42:33 -08001360 * @file: file pointer, not actually used
Casey Schauflere114e472008-02-04 22:29:50 -08001361 * @buf: where to get the data from
1362 * @count: bytes sent
1363 * @ppos: where to start
1364 *
1365 * Returns number of bytes written or error code, as appropriate
1366 */
1367static ssize_t smk_write_doi(struct file *file, const char __user *buf,
1368 size_t count, loff_t *ppos)
1369{
1370 char temp[80];
1371 int i;
1372
Casey Schaufler1880eff2012-06-05 15:28:30 -07001373 if (!smack_privileged(CAP_MAC_ADMIN))
Casey Schauflere114e472008-02-04 22:29:50 -08001374 return -EPERM;
1375
1376 if (count >= sizeof(temp) || count == 0)
1377 return -EINVAL;
1378
1379 if (copy_from_user(temp, buf, count) != 0)
1380 return -EFAULT;
1381
1382 temp[count] = '\0';
1383
1384 if (sscanf(temp, "%d", &i) != 1)
1385 return -EINVAL;
1386
1387 smk_cipso_doi_value = i;
1388
1389 smk_cipso_doi();
1390
1391 return count;
1392}
1393
1394static const struct file_operations smk_doi_ops = {
1395 .read = smk_read_doi,
1396 .write = smk_write_doi,
Arnd Bergmann6038f372010-08-15 18:52:59 +02001397 .llseek = default_llseek,
Casey Schauflere114e472008-02-04 22:29:50 -08001398};
1399
1400/**
1401 * smk_read_direct - read() for /smack/direct
1402 * @filp: file pointer, not actually used
1403 * @buf: where to put the result
1404 * @count: maximum to send along
1405 * @ppos: where to start
1406 *
1407 * Returns number of bytes read or error code, as appropriate
1408 */
1409static ssize_t smk_read_direct(struct file *filp, char __user *buf,
1410 size_t count, loff_t *ppos)
1411{
1412 char temp[80];
1413 ssize_t rc;
1414
1415 if (*ppos != 0)
1416 return 0;
1417
1418 sprintf(temp, "%d", smack_cipso_direct);
1419 rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
1420
1421 return rc;
1422}
1423
1424/**
1425 * smk_write_direct - write() for /smack/direct
Randy Dunlap251a2a92009-02-18 11:42:33 -08001426 * @file: file pointer, not actually used
Casey Schauflere114e472008-02-04 22:29:50 -08001427 * @buf: where to get the data from
1428 * @count: bytes sent
1429 * @ppos: where to start
1430 *
1431 * Returns number of bytes written or error code, as appropriate
1432 */
1433static ssize_t smk_write_direct(struct file *file, const char __user *buf,
1434 size_t count, loff_t *ppos)
1435{
Casey Schauflerf7112e62012-05-06 15:22:02 -07001436 struct smack_known *skp;
Casey Schauflere114e472008-02-04 22:29:50 -08001437 char temp[80];
1438 int i;
1439
Casey Schaufler1880eff2012-06-05 15:28:30 -07001440 if (!smack_privileged(CAP_MAC_ADMIN))
Casey Schauflere114e472008-02-04 22:29:50 -08001441 return -EPERM;
1442
1443 if (count >= sizeof(temp) || count == 0)
1444 return -EINVAL;
1445
1446 if (copy_from_user(temp, buf, count) != 0)
1447 return -EFAULT;
1448
1449 temp[count] = '\0';
1450
1451 if (sscanf(temp, "%d", &i) != 1)
1452 return -EINVAL;
1453
Casey Schauflerf7112e62012-05-06 15:22:02 -07001454 /*
1455 * Don't do anything if the value hasn't actually changed.
1456 * If it is changing reset the level on entries that were
1457 * set up to be direct when they were created.
1458 */
1459 if (smack_cipso_direct != i) {
1460 mutex_lock(&smack_known_lock);
1461 list_for_each_entry_rcu(skp, &smack_known_list, list)
1462 if (skp->smk_netlabel.attr.mls.lvl ==
1463 smack_cipso_direct)
1464 skp->smk_netlabel.attr.mls.lvl = i;
1465 smack_cipso_direct = i;
1466 mutex_unlock(&smack_known_lock);
1467 }
Casey Schauflere114e472008-02-04 22:29:50 -08001468
1469 return count;
1470}
1471
1472static const struct file_operations smk_direct_ops = {
1473 .read = smk_read_direct,
1474 .write = smk_write_direct,
Arnd Bergmann6038f372010-08-15 18:52:59 +02001475 .llseek = default_llseek,
Casey Schauflere114e472008-02-04 22:29:50 -08001476};
1477
1478/**
Casey Schauflerf7112e62012-05-06 15:22:02 -07001479 * smk_read_mapped - read() for /smack/mapped
1480 * @filp: file pointer, not actually used
1481 * @buf: where to put the result
1482 * @count: maximum to send along
1483 * @ppos: where to start
1484 *
1485 * Returns number of bytes read or error code, as appropriate
1486 */
1487static ssize_t smk_read_mapped(struct file *filp, char __user *buf,
1488 size_t count, loff_t *ppos)
1489{
1490 char temp[80];
1491 ssize_t rc;
1492
1493 if (*ppos != 0)
1494 return 0;
1495
1496 sprintf(temp, "%d", smack_cipso_mapped);
1497 rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
1498
1499 return rc;
1500}
1501
1502/**
1503 * smk_write_mapped - write() for /smack/mapped
1504 * @file: file pointer, not actually used
1505 * @buf: where to get the data from
1506 * @count: bytes sent
1507 * @ppos: where to start
1508 *
1509 * Returns number of bytes written or error code, as appropriate
1510 */
1511static ssize_t smk_write_mapped(struct file *file, const char __user *buf,
1512 size_t count, loff_t *ppos)
1513{
1514 struct smack_known *skp;
1515 char temp[80];
1516 int i;
1517
Casey Schaufler1880eff2012-06-05 15:28:30 -07001518 if (!smack_privileged(CAP_MAC_ADMIN))
Casey Schauflerf7112e62012-05-06 15:22:02 -07001519 return -EPERM;
1520
1521 if (count >= sizeof(temp) || count == 0)
1522 return -EINVAL;
1523
1524 if (copy_from_user(temp, buf, count) != 0)
1525 return -EFAULT;
1526
1527 temp[count] = '\0';
1528
1529 if (sscanf(temp, "%d", &i) != 1)
1530 return -EINVAL;
1531
1532 /*
1533 * Don't do anything if the value hasn't actually changed.
1534 * If it is changing reset the level on entries that were
1535 * set up to be mapped when they were created.
1536 */
1537 if (smack_cipso_mapped != i) {
1538 mutex_lock(&smack_known_lock);
1539 list_for_each_entry_rcu(skp, &smack_known_list, list)
1540 if (skp->smk_netlabel.attr.mls.lvl ==
1541 smack_cipso_mapped)
1542 skp->smk_netlabel.attr.mls.lvl = i;
1543 smack_cipso_mapped = i;
1544 mutex_unlock(&smack_known_lock);
1545 }
1546
1547 return count;
1548}
1549
1550static const struct file_operations smk_mapped_ops = {
1551 .read = smk_read_mapped,
1552 .write = smk_write_mapped,
1553 .llseek = default_llseek,
1554};
1555
1556/**
Casey Schauflere114e472008-02-04 22:29:50 -08001557 * smk_read_ambient - read() for /smack/ambient
1558 * @filp: file pointer, not actually used
1559 * @buf: where to put the result
1560 * @cn: maximum to send along
1561 * @ppos: where to start
1562 *
1563 * Returns number of bytes read or error code, as appropriate
1564 */
1565static ssize_t smk_read_ambient(struct file *filp, char __user *buf,
1566 size_t cn, loff_t *ppos)
1567{
1568 ssize_t rc;
Casey Schauflere114e472008-02-04 22:29:50 -08001569 int asize;
1570
1571 if (*ppos != 0)
1572 return 0;
1573 /*
1574 * Being careful to avoid a problem in the case where
1575 * smack_net_ambient gets changed in midstream.
Casey Schauflere114e472008-02-04 22:29:50 -08001576 */
Casey Schaufler4bc87e62008-02-15 15:24:25 -08001577 mutex_lock(&smack_ambient_lock);
Casey Schauflere114e472008-02-04 22:29:50 -08001578
Casey Schaufler2f823ff2013-05-22 18:43:03 -07001579 asize = strlen(smack_net_ambient->smk_known) + 1;
Casey Schauflere114e472008-02-04 22:29:50 -08001580
Casey Schaufler4bc87e62008-02-15 15:24:25 -08001581 if (cn >= asize)
1582 rc = simple_read_from_buffer(buf, cn, ppos,
Casey Schaufler2f823ff2013-05-22 18:43:03 -07001583 smack_net_ambient->smk_known,
1584 asize);
Casey Schaufler4bc87e62008-02-15 15:24:25 -08001585 else
1586 rc = -EINVAL;
1587
1588 mutex_unlock(&smack_ambient_lock);
Casey Schauflere114e472008-02-04 22:29:50 -08001589
1590 return rc;
1591}
1592
1593/**
1594 * smk_write_ambient - write() for /smack/ambient
Randy Dunlap251a2a92009-02-18 11:42:33 -08001595 * @file: file pointer, not actually used
Casey Schauflere114e472008-02-04 22:29:50 -08001596 * @buf: where to get the data from
1597 * @count: bytes sent
1598 * @ppos: where to start
1599 *
1600 * Returns number of bytes written or error code, as appropriate
1601 */
1602static ssize_t smk_write_ambient(struct file *file, const char __user *buf,
1603 size_t count, loff_t *ppos)
1604{
Casey Schaufler2f823ff2013-05-22 18:43:03 -07001605 struct smack_known *skp;
Casey Schaufler4bc87e62008-02-15 15:24:25 -08001606 char *oldambient;
Casey Schauflerf7112e62012-05-06 15:22:02 -07001607 char *data;
1608 int rc = count;
Casey Schauflere114e472008-02-04 22:29:50 -08001609
Casey Schaufler1880eff2012-06-05 15:28:30 -07001610 if (!smack_privileged(CAP_MAC_ADMIN))
Casey Schauflere114e472008-02-04 22:29:50 -08001611 return -EPERM;
1612
Casey Schauflerf7112e62012-05-06 15:22:02 -07001613 data = kzalloc(count + 1, GFP_KERNEL);
1614 if (data == NULL)
1615 return -ENOMEM;
Casey Schauflere114e472008-02-04 22:29:50 -08001616
Casey Schauflerf7112e62012-05-06 15:22:02 -07001617 if (copy_from_user(data, buf, count) != 0) {
1618 rc = -EFAULT;
1619 goto out;
1620 }
Casey Schauflere114e472008-02-04 22:29:50 -08001621
Casey Schaufler2f823ff2013-05-22 18:43:03 -07001622 skp = smk_import_entry(data, count);
1623 if (skp == NULL) {
Casey Schauflerf7112e62012-05-06 15:22:02 -07001624 rc = -EINVAL;
1625 goto out;
1626 }
Casey Schauflere114e472008-02-04 22:29:50 -08001627
Casey Schaufler4bc87e62008-02-15 15:24:25 -08001628 mutex_lock(&smack_ambient_lock);
1629
Casey Schaufler2f823ff2013-05-22 18:43:03 -07001630 oldambient = smack_net_ambient->smk_known;
1631 smack_net_ambient = skp;
Casey Schaufler4bc87e62008-02-15 15:24:25 -08001632 smk_unlbl_ambient(oldambient);
1633
1634 mutex_unlock(&smack_ambient_lock);
Casey Schauflere114e472008-02-04 22:29:50 -08001635
Casey Schauflerf7112e62012-05-06 15:22:02 -07001636out:
1637 kfree(data);
1638 return rc;
Casey Schauflere114e472008-02-04 22:29:50 -08001639}
1640
1641static const struct file_operations smk_ambient_ops = {
1642 .read = smk_read_ambient,
1643 .write = smk_write_ambient,
Arnd Bergmann6038f372010-08-15 18:52:59 +02001644 .llseek = default_llseek,
Casey Schauflere114e472008-02-04 22:29:50 -08001645};
1646
Casey Schaufler15446232008-07-30 15:37:11 -07001647/**
Casey Schaufler00f84f32013-12-23 11:07:10 -08001648 * smk_read_onlycap - read() for smackfs/onlycap
Casey Schaufler15446232008-07-30 15:37:11 -07001649 * @filp: file pointer, not actually used
1650 * @buf: where to put the result
1651 * @cn: maximum to send along
1652 * @ppos: where to start
1653 *
1654 * Returns number of bytes read or error code, as appropriate
1655 */
1656static ssize_t smk_read_onlycap(struct file *filp, char __user *buf,
1657 size_t cn, loff_t *ppos)
1658{
1659 char *smack = "";
1660 ssize_t rc = -EINVAL;
1661 int asize;
1662
1663 if (*ppos != 0)
1664 return 0;
1665
1666 if (smack_onlycap != NULL)
Casey Schaufler00f84f32013-12-23 11:07:10 -08001667 smack = smack_onlycap->smk_known;
Casey Schaufler15446232008-07-30 15:37:11 -07001668
1669 asize = strlen(smack) + 1;
1670
1671 if (cn >= asize)
1672 rc = simple_read_from_buffer(buf, cn, ppos, smack, asize);
1673
1674 return rc;
1675}
1676
1677/**
Casey Schaufler00f84f32013-12-23 11:07:10 -08001678 * smk_write_onlycap - write() for smackfs/onlycap
Randy Dunlap251a2a92009-02-18 11:42:33 -08001679 * @file: file pointer, not actually used
Casey Schaufler15446232008-07-30 15:37:11 -07001680 * @buf: where to get the data from
1681 * @count: bytes sent
1682 * @ppos: where to start
1683 *
1684 * Returns number of bytes written or error code, as appropriate
1685 */
1686static ssize_t smk_write_onlycap(struct file *file, const char __user *buf,
1687 size_t count, loff_t *ppos)
1688{
Casey Schauflerf7112e62012-05-06 15:22:02 -07001689 char *data;
Casey Schaufler2f823ff2013-05-22 18:43:03 -07001690 struct smack_known *skp = smk_of_task(current->cred->security);
Casey Schauflerf7112e62012-05-06 15:22:02 -07001691 int rc = count;
Casey Schaufler15446232008-07-30 15:37:11 -07001692
Casey Schaufler1880eff2012-06-05 15:28:30 -07001693 if (!smack_privileged(CAP_MAC_ADMIN))
Casey Schaufler15446232008-07-30 15:37:11 -07001694 return -EPERM;
1695
1696 /*
1697 * This can be done using smk_access() but is done
1698 * explicitly for clarity. The smk_access() implementation
1699 * would use smk_access(smack_onlycap, MAY_WRITE)
1700 */
Casey Schaufler00f84f32013-12-23 11:07:10 -08001701 if (smack_onlycap != NULL && smack_onlycap != skp)
Casey Schaufler15446232008-07-30 15:37:11 -07001702 return -EPERM;
1703
Konstantin Khlebnikovb862e562014-08-07 20:52:43 +04001704 data = kzalloc(count + 1, GFP_KERNEL);
Casey Schauflerf7112e62012-05-06 15:22:02 -07001705 if (data == NULL)
1706 return -ENOMEM;
Casey Schaufler15446232008-07-30 15:37:11 -07001707
1708 /*
1709 * Should the null string be passed in unset the onlycap value.
1710 * This seems like something to be careful with as usually
1711 * smk_import only expects to return NULL for errors. It
1712 * is usually the case that a nullstring or "\n" would be
1713 * bad to pass to smk_import but in fact this is useful here.
Casey Schauflerf7112e62012-05-06 15:22:02 -07001714 *
1715 * smk_import will also reject a label beginning with '-',
1716 * so "-usecapabilities" will also work.
Casey Schaufler15446232008-07-30 15:37:11 -07001717 */
Casey Schauflerf7112e62012-05-06 15:22:02 -07001718 if (copy_from_user(data, buf, count) != 0)
1719 rc = -EFAULT;
1720 else
Casey Schaufler00f84f32013-12-23 11:07:10 -08001721 smack_onlycap = smk_import_entry(data, count);
Casey Schaufler15446232008-07-30 15:37:11 -07001722
Casey Schauflerf7112e62012-05-06 15:22:02 -07001723 kfree(data);
1724 return rc;
Casey Schaufler15446232008-07-30 15:37:11 -07001725}
1726
1727static const struct file_operations smk_onlycap_ops = {
1728 .read = smk_read_onlycap,
1729 .write = smk_write_onlycap,
Arnd Bergmann6038f372010-08-15 18:52:59 +02001730 .llseek = default_llseek,
Casey Schaufler15446232008-07-30 15:37:11 -07001731};
1732
Casey Schauflerbf4b2fe2015-03-21 18:26:40 -07001733#ifdef CONFIG_SECURITY_SMACK_BRINGUP
1734/**
1735 * smk_read_unconfined - read() for smackfs/unconfined
1736 * @filp: file pointer, not actually used
1737 * @buf: where to put the result
1738 * @cn: maximum to send along
1739 * @ppos: where to start
1740 *
1741 * Returns number of bytes read or error code, as appropriate
1742 */
1743static ssize_t smk_read_unconfined(struct file *filp, char __user *buf,
1744 size_t cn, loff_t *ppos)
1745{
1746 char *smack = "";
1747 ssize_t rc = -EINVAL;
1748 int asize;
1749
1750 if (*ppos != 0)
1751 return 0;
1752
1753 if (smack_unconfined != NULL)
1754 smack = smack_unconfined->smk_known;
1755
1756 asize = strlen(smack) + 1;
1757
1758 if (cn >= asize)
1759 rc = simple_read_from_buffer(buf, cn, ppos, smack, asize);
1760
1761 return rc;
1762}
1763
1764/**
1765 * smk_write_unconfined - write() for smackfs/unconfined
1766 * @file: file pointer, not actually used
1767 * @buf: where to get the data from
1768 * @count: bytes sent
1769 * @ppos: where to start
1770 *
1771 * Returns number of bytes written or error code, as appropriate
1772 */
1773static ssize_t smk_write_unconfined(struct file *file, const char __user *buf,
1774 size_t count, loff_t *ppos)
1775{
1776 char *data;
1777 int rc = count;
1778
1779 if (!smack_privileged(CAP_MAC_ADMIN))
1780 return -EPERM;
1781
1782 data = kzalloc(count + 1, GFP_KERNEL);
1783 if (data == NULL)
1784 return -ENOMEM;
1785
1786 /*
1787 * Should the null string be passed in unset the unconfined value.
1788 * This seems like something to be careful with as usually
1789 * smk_import only expects to return NULL for errors. It
1790 * is usually the case that a nullstring or "\n" would be
1791 * bad to pass to smk_import but in fact this is useful here.
1792 *
1793 * smk_import will also reject a label beginning with '-',
1794 * so "-confine" will also work.
1795 */
1796 if (copy_from_user(data, buf, count) != 0)
1797 rc = -EFAULT;
1798 else
1799 smack_unconfined = smk_import_entry(data, count);
1800
1801 kfree(data);
1802 return rc;
1803}
1804
1805static const struct file_operations smk_unconfined_ops = {
1806 .read = smk_read_unconfined,
1807 .write = smk_write_unconfined,
1808 .llseek = default_llseek,
1809};
1810#endif /* CONFIG_SECURITY_SMACK_BRINGUP */
1811
Casey Schauflere114e472008-02-04 22:29:50 -08001812/**
Etienne Bassetecfcc532009-04-08 20:40:06 +02001813 * smk_read_logging - read() for /smack/logging
1814 * @filp: file pointer, not actually used
1815 * @buf: where to put the result
1816 * @cn: maximum to send along
1817 * @ppos: where to start
1818 *
1819 * Returns number of bytes read or error code, as appropriate
1820 */
1821static ssize_t smk_read_logging(struct file *filp, char __user *buf,
1822 size_t count, loff_t *ppos)
1823{
1824 char temp[32];
1825 ssize_t rc;
1826
1827 if (*ppos != 0)
1828 return 0;
1829
1830 sprintf(temp, "%d\n", log_policy);
1831 rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
1832 return rc;
1833}
1834
1835/**
1836 * smk_write_logging - write() for /smack/logging
1837 * @file: file pointer, not actually used
1838 * @buf: where to get the data from
1839 * @count: bytes sent
1840 * @ppos: where to start
1841 *
1842 * Returns number of bytes written or error code, as appropriate
1843 */
1844static ssize_t smk_write_logging(struct file *file, const char __user *buf,
1845 size_t count, loff_t *ppos)
1846{
1847 char temp[32];
1848 int i;
1849
Casey Schaufler1880eff2012-06-05 15:28:30 -07001850 if (!smack_privileged(CAP_MAC_ADMIN))
Etienne Bassetecfcc532009-04-08 20:40:06 +02001851 return -EPERM;
1852
1853 if (count >= sizeof(temp) || count == 0)
1854 return -EINVAL;
1855
1856 if (copy_from_user(temp, buf, count) != 0)
1857 return -EFAULT;
1858
1859 temp[count] = '\0';
1860
1861 if (sscanf(temp, "%d", &i) != 1)
1862 return -EINVAL;
1863 if (i < 0 || i > 3)
1864 return -EINVAL;
1865 log_policy = i;
1866 return count;
1867}
1868
1869
1870
1871static const struct file_operations smk_logging_ops = {
1872 .read = smk_read_logging,
1873 .write = smk_write_logging,
Arnd Bergmann6038f372010-08-15 18:52:59 +02001874 .llseek = default_llseek,
Etienne Bassetecfcc532009-04-08 20:40:06 +02001875};
Casey Schaufler7898e1f2011-01-17 08:05:27 -08001876
1877/*
1878 * Seq_file read operations for /smack/load-self
1879 */
1880
1881static void *load_self_seq_start(struct seq_file *s, loff_t *pos)
1882{
1883 struct task_smack *tsp = current_security();
1884
Casey Schaufler40809562011-11-10 15:02:22 -08001885 return smk_seq_start(s, pos, &tsp->smk_rules);
Casey Schaufler7898e1f2011-01-17 08:05:27 -08001886}
1887
1888static void *load_self_seq_next(struct seq_file *s, void *v, loff_t *pos)
1889{
1890 struct task_smack *tsp = current_security();
Casey Schaufler7898e1f2011-01-17 08:05:27 -08001891
Casey Schaufler40809562011-11-10 15:02:22 -08001892 return smk_seq_next(s, v, pos, &tsp->smk_rules);
Casey Schaufler7898e1f2011-01-17 08:05:27 -08001893}
1894
1895static int load_self_seq_show(struct seq_file *s, void *v)
1896{
1897 struct list_head *list = v;
1898 struct smack_rule *srp =
1899 list_entry(list, struct smack_rule, list);
1900
Casey Schauflerf7112e62012-05-06 15:22:02 -07001901 smk_rule_show(s, srp, SMK_LABELLEN);
Casey Schaufler7898e1f2011-01-17 08:05:27 -08001902
1903 return 0;
1904}
1905
Casey Schaufler7898e1f2011-01-17 08:05:27 -08001906static const struct seq_operations load_self_seq_ops = {
1907 .start = load_self_seq_start,
1908 .next = load_self_seq_next,
1909 .show = load_self_seq_show,
Casey Schaufler40809562011-11-10 15:02:22 -08001910 .stop = smk_seq_stop,
Casey Schaufler7898e1f2011-01-17 08:05:27 -08001911};
1912
1913
1914/**
Casey Schauflerf7112e62012-05-06 15:22:02 -07001915 * smk_open_load_self - open() for /smack/load-self2
Casey Schaufler7898e1f2011-01-17 08:05:27 -08001916 * @inode: inode structure representing file
1917 * @file: "load" file pointer
1918 *
1919 * For reading, use load_seq_* seq_file reading operations.
1920 */
1921static int smk_open_load_self(struct inode *inode, struct file *file)
1922{
1923 return seq_open(file, &load_self_seq_ops);
1924}
1925
1926/**
1927 * smk_write_load_self - write() for /smack/load-self
1928 * @file: file pointer, not actually used
1929 * @buf: where to get the data from
1930 * @count: bytes sent
1931 * @ppos: where to start - must be 0
1932 *
1933 */
1934static ssize_t smk_write_load_self(struct file *file, const char __user *buf,
1935 size_t count, loff_t *ppos)
1936{
1937 struct task_smack *tsp = current_security();
1938
Casey Schauflerf7112e62012-05-06 15:22:02 -07001939 return smk_write_rules_list(file, buf, count, ppos, &tsp->smk_rules,
1940 &tsp->smk_rules_lock, SMK_FIXED24_FMT);
Casey Schaufler7898e1f2011-01-17 08:05:27 -08001941}
1942
1943static const struct file_operations smk_load_self_ops = {
1944 .open = smk_open_load_self,
1945 .read = seq_read,
1946 .llseek = seq_lseek,
1947 .write = smk_write_load_self,
1948 .release = seq_release,
1949};
Jarkko Sakkinen828716c2011-09-08 10:12:01 +03001950
1951/**
Casey Schauflerf7112e62012-05-06 15:22:02 -07001952 * smk_user_access - handle access check transaction
1953 * @file: file pointer
1954 * @buf: data from user space
1955 * @count: bytes sent
1956 * @ppos: where to start - must be 0
1957 */
1958static ssize_t smk_user_access(struct file *file, const char __user *buf,
1959 size_t count, loff_t *ppos, int format)
1960{
Rafal Krypae05b6f92013-01-10 19:42:00 +01001961 struct smack_parsed_rule rule;
Casey Schauflerf7112e62012-05-06 15:22:02 -07001962 char *data;
Casey Schauflerf7112e62012-05-06 15:22:02 -07001963 int res;
1964
1965 data = simple_transaction_get(file, buf, count);
1966 if (IS_ERR(data))
1967 return PTR_ERR(data);
1968
1969 if (format == SMK_FIXED24_FMT) {
1970 if (count < SMK_LOADLEN)
1971 return -EINVAL;
1972 res = smk_parse_rule(data, &rule, 0);
1973 } else {
1974 /*
Rafal Krypa10289b02013-08-09 11:47:07 +02001975 * simple_transaction_get() returns null-terminated data
Casey Schauflerf7112e62012-05-06 15:22:02 -07001976 */
Rafal Krypa10289b02013-08-09 11:47:07 +02001977 res = smk_parse_long_rule(data, &rule, 0, 3);
Casey Schauflerf7112e62012-05-06 15:22:02 -07001978 }
1979
Jarkko Sakkinen398ce072013-11-28 19:16:46 +02001980 if (res >= 0)
1981 res = smk_access(rule.smk_subject, rule.smk_object,
1982 rule.smk_access1, NULL);
1983 else if (res != -ENOENT)
Casey Schauflerf7112e62012-05-06 15:22:02 -07001984 return -EINVAL;
1985
Casey Schauflerd166c802014-08-27 14:51:27 -07001986 /*
1987 * smk_access() can return a value > 0 in the "bringup" case.
1988 */
1989 data[0] = res >= 0 ? '1' : '0';
Casey Schauflerf7112e62012-05-06 15:22:02 -07001990 data[1] = '\0';
1991
1992 simple_transaction_set(file, 2);
1993
1994 if (format == SMK_FIXED24_FMT)
1995 return SMK_LOADLEN;
1996 return count;
1997}
1998
1999/**
Jarkko Sakkinen828716c2011-09-08 10:12:01 +03002000 * smk_write_access - handle access check transaction
2001 * @file: file pointer
2002 * @buf: data from user space
2003 * @count: bytes sent
2004 * @ppos: where to start - must be 0
2005 */
2006static ssize_t smk_write_access(struct file *file, const char __user *buf,
2007 size_t count, loff_t *ppos)
2008{
Casey Schauflerf7112e62012-05-06 15:22:02 -07002009 return smk_user_access(file, buf, count, ppos, SMK_FIXED24_FMT);
Jarkko Sakkinen828716c2011-09-08 10:12:01 +03002010}
2011
2012static const struct file_operations smk_access_ops = {
2013 .write = smk_write_access,
2014 .read = simple_transaction_read,
2015 .release = simple_transaction_release,
2016 .llseek = generic_file_llseek,
2017};
2018
Casey Schauflerf7112e62012-05-06 15:22:02 -07002019
2020/*
2021 * Seq_file read operations for /smack/load2
2022 */
2023
2024static int load2_seq_show(struct seq_file *s, void *v)
2025{
2026 struct list_head *list = v;
2027 struct smack_master_list *smlp =
2028 list_entry(list, struct smack_master_list, list);
2029
2030 smk_rule_show(s, smlp->smk_rule, SMK_LONGLABEL);
2031
2032 return 0;
2033}
2034
2035static const struct seq_operations load2_seq_ops = {
2036 .start = load2_seq_start,
2037 .next = load2_seq_next,
2038 .show = load2_seq_show,
2039 .stop = smk_seq_stop,
2040};
2041
2042/**
2043 * smk_open_load2 - open() for /smack/load2
2044 * @inode: inode structure representing file
2045 * @file: "load2" file pointer
2046 *
2047 * For reading, use load2_seq_* seq_file reading operations.
2048 */
2049static int smk_open_load2(struct inode *inode, struct file *file)
2050{
2051 return seq_open(file, &load2_seq_ops);
2052}
2053
2054/**
2055 * smk_write_load2 - write() for /smack/load2
2056 * @file: file pointer, not actually used
2057 * @buf: where to get the data from
2058 * @count: bytes sent
2059 * @ppos: where to start - must be 0
2060 *
2061 */
2062static ssize_t smk_write_load2(struct file *file, const char __user *buf,
2063 size_t count, loff_t *ppos)
2064{
2065 /*
2066 * Must have privilege.
2067 */
Casey Schaufler1880eff2012-06-05 15:28:30 -07002068 if (!smack_privileged(CAP_MAC_ADMIN))
Casey Schauflerf7112e62012-05-06 15:22:02 -07002069 return -EPERM;
2070
2071 return smk_write_rules_list(file, buf, count, ppos, NULL, NULL,
2072 SMK_LONG_FMT);
2073}
2074
2075static const struct file_operations smk_load2_ops = {
2076 .open = smk_open_load2,
2077 .read = seq_read,
2078 .llseek = seq_lseek,
2079 .write = smk_write_load2,
2080 .release = seq_release,
2081};
2082
2083/*
2084 * Seq_file read operations for /smack/load-self2
2085 */
2086
2087static void *load_self2_seq_start(struct seq_file *s, loff_t *pos)
2088{
2089 struct task_smack *tsp = current_security();
2090
2091 return smk_seq_start(s, pos, &tsp->smk_rules);
2092}
2093
2094static void *load_self2_seq_next(struct seq_file *s, void *v, loff_t *pos)
2095{
2096 struct task_smack *tsp = current_security();
2097
2098 return smk_seq_next(s, v, pos, &tsp->smk_rules);
2099}
2100
2101static int load_self2_seq_show(struct seq_file *s, void *v)
2102{
2103 struct list_head *list = v;
2104 struct smack_rule *srp =
2105 list_entry(list, struct smack_rule, list);
2106
2107 smk_rule_show(s, srp, SMK_LONGLABEL);
2108
2109 return 0;
2110}
2111
2112static const struct seq_operations load_self2_seq_ops = {
2113 .start = load_self2_seq_start,
2114 .next = load_self2_seq_next,
2115 .show = load_self2_seq_show,
2116 .stop = smk_seq_stop,
2117};
2118
2119/**
2120 * smk_open_load_self2 - open() for /smack/load-self2
2121 * @inode: inode structure representing file
2122 * @file: "load" file pointer
2123 *
2124 * For reading, use load_seq_* seq_file reading operations.
2125 */
2126static int smk_open_load_self2(struct inode *inode, struct file *file)
2127{
2128 return seq_open(file, &load_self2_seq_ops);
2129}
2130
2131/**
2132 * smk_write_load_self2 - write() for /smack/load-self2
2133 * @file: file pointer, not actually used
2134 * @buf: where to get the data from
2135 * @count: bytes sent
2136 * @ppos: where to start - must be 0
2137 *
2138 */
2139static ssize_t smk_write_load_self2(struct file *file, const char __user *buf,
2140 size_t count, loff_t *ppos)
2141{
2142 struct task_smack *tsp = current_security();
2143
2144 return smk_write_rules_list(file, buf, count, ppos, &tsp->smk_rules,
2145 &tsp->smk_rules_lock, SMK_LONG_FMT);
2146}
2147
2148static const struct file_operations smk_load_self2_ops = {
2149 .open = smk_open_load_self2,
2150 .read = seq_read,
2151 .llseek = seq_lseek,
2152 .write = smk_write_load_self2,
2153 .release = seq_release,
2154};
2155
2156/**
2157 * smk_write_access2 - handle access check transaction
2158 * @file: file pointer
2159 * @buf: data from user space
2160 * @count: bytes sent
2161 * @ppos: where to start - must be 0
2162 */
2163static ssize_t smk_write_access2(struct file *file, const char __user *buf,
2164 size_t count, loff_t *ppos)
2165{
2166 return smk_user_access(file, buf, count, ppos, SMK_LONG_FMT);
2167}
2168
2169static const struct file_operations smk_access2_ops = {
2170 .write = smk_write_access2,
2171 .read = simple_transaction_read,
2172 .release = simple_transaction_release,
2173 .llseek = generic_file_llseek,
2174};
2175
Etienne Bassetecfcc532009-04-08 20:40:06 +02002176/**
Rafal Krypa449543b2012-07-11 17:49:30 +02002177 * smk_write_revoke_subj - write() for /smack/revoke-subject
2178 * @file: file pointer
2179 * @buf: data from user space
2180 * @count: bytes sent
2181 * @ppos: where to start - must be 0
2182 */
2183static ssize_t smk_write_revoke_subj(struct file *file, const char __user *buf,
2184 size_t count, loff_t *ppos)
2185{
2186 char *data = NULL;
2187 const char *cp = NULL;
2188 struct smack_known *skp;
2189 struct smack_rule *sp;
2190 struct list_head *rule_list;
2191 struct mutex *rule_lock;
2192 int rc = count;
2193
2194 if (*ppos != 0)
2195 return -EINVAL;
2196
2197 if (!smack_privileged(CAP_MAC_ADMIN))
2198 return -EPERM;
2199
2200 if (count == 0 || count > SMK_LONGLABEL)
2201 return -EINVAL;
2202
2203 data = kzalloc(count, GFP_KERNEL);
2204 if (data == NULL)
2205 return -ENOMEM;
2206
2207 if (copy_from_user(data, buf, count) != 0) {
2208 rc = -EFAULT;
2209 goto free_out;
2210 }
2211
2212 cp = smk_parse_smack(data, count);
2213 if (cp == NULL) {
2214 rc = -EINVAL;
2215 goto free_out;
2216 }
2217
2218 skp = smk_find_entry(cp);
Rafal Krypad15d9fad2012-11-27 16:28:11 +01002219 if (skp == NULL)
Rafal Krypa449543b2012-07-11 17:49:30 +02002220 goto free_out;
Rafal Krypa449543b2012-07-11 17:49:30 +02002221
2222 rule_list = &skp->smk_rules;
2223 rule_lock = &skp->smk_rules_lock;
2224
2225 mutex_lock(rule_lock);
2226
2227 list_for_each_entry_rcu(sp, rule_list, list)
2228 sp->smk_access = 0;
2229
2230 mutex_unlock(rule_lock);
2231
2232free_out:
2233 kfree(data);
2234 kfree(cp);
2235 return rc;
2236}
2237
2238static const struct file_operations smk_revoke_subj_ops = {
2239 .write = smk_write_revoke_subj,
2240 .read = simple_transaction_read,
2241 .release = simple_transaction_release,
2242 .llseek = generic_file_llseek,
2243};
2244
Casey Schauflere9307232012-11-01 18:14:32 -07002245static struct kset *smackfs_kset;
2246/**
2247 * smk_init_sysfs - initialize /sys/fs/smackfs
2248 *
2249 */
2250static int smk_init_sysfs(void)
2251{
2252 smackfs_kset = kset_create_and_add("smackfs", NULL, fs_kobj);
2253 if (!smackfs_kset)
2254 return -ENOMEM;
2255 return 0;
2256}
2257
Rafal Krypa449543b2012-07-11 17:49:30 +02002258/**
Rafal Krypae05b6f92013-01-10 19:42:00 +01002259 * smk_write_change_rule - write() for /smack/change-rule
2260 * @file: file pointer
2261 * @buf: data from user space
2262 * @count: bytes sent
2263 * @ppos: where to start - must be 0
2264 */
2265static ssize_t smk_write_change_rule(struct file *file, const char __user *buf,
2266 size_t count, loff_t *ppos)
2267{
2268 /*
2269 * Must have privilege.
2270 */
Casey Schaufler4afde482013-12-19 13:23:26 -08002271 if (!smack_privileged(CAP_MAC_ADMIN))
Rafal Krypae05b6f92013-01-10 19:42:00 +01002272 return -EPERM;
2273
2274 return smk_write_rules_list(file, buf, count, ppos, NULL, NULL,
2275 SMK_CHANGE_FMT);
2276}
2277
2278static const struct file_operations smk_change_rule_ops = {
2279 .write = smk_write_change_rule,
2280 .read = simple_transaction_read,
2281 .release = simple_transaction_release,
2282 .llseek = generic_file_llseek,
2283};
2284
2285/**
Casey Schaufler00f84f32013-12-23 11:07:10 -08002286 * smk_read_syslog - read() for smackfs/syslog
2287 * @filp: file pointer, not actually used
2288 * @buf: where to put the result
2289 * @cn: maximum to send along
2290 * @ppos: where to start
2291 *
2292 * Returns number of bytes read or error code, as appropriate
2293 */
2294static ssize_t smk_read_syslog(struct file *filp, char __user *buf,
2295 size_t cn, loff_t *ppos)
2296{
2297 struct smack_known *skp;
2298 ssize_t rc = -EINVAL;
2299 int asize;
2300
2301 if (*ppos != 0)
2302 return 0;
2303
2304 if (smack_syslog_label == NULL)
2305 skp = &smack_known_star;
2306 else
2307 skp = smack_syslog_label;
2308
2309 asize = strlen(skp->smk_known) + 1;
2310
2311 if (cn >= asize)
2312 rc = simple_read_from_buffer(buf, cn, ppos, skp->smk_known,
2313 asize);
2314
2315 return rc;
2316}
2317
2318/**
2319 * smk_write_syslog - write() for smackfs/syslog
2320 * @file: file pointer, not actually used
2321 * @buf: where to get the data from
2322 * @count: bytes sent
2323 * @ppos: where to start
2324 *
2325 * Returns number of bytes written or error code, as appropriate
2326 */
2327static ssize_t smk_write_syslog(struct file *file, const char __user *buf,
2328 size_t count, loff_t *ppos)
2329{
2330 char *data;
2331 struct smack_known *skp;
2332 int rc = count;
2333
2334 if (!smack_privileged(CAP_MAC_ADMIN))
2335 return -EPERM;
2336
Konstantin Khlebnikovb862e562014-08-07 20:52:43 +04002337 data = kzalloc(count + 1, GFP_KERNEL);
Casey Schaufler00f84f32013-12-23 11:07:10 -08002338 if (data == NULL)
2339 return -ENOMEM;
2340
2341 if (copy_from_user(data, buf, count) != 0)
2342 rc = -EFAULT;
2343 else {
2344 skp = smk_import_entry(data, count);
2345 if (skp == NULL)
2346 rc = -EINVAL;
2347 else
2348 smack_syslog_label = smk_import_entry(data, count);
2349 }
2350
2351 kfree(data);
2352 return rc;
2353}
2354
2355static const struct file_operations smk_syslog_ops = {
2356 .read = smk_read_syslog,
2357 .write = smk_write_syslog,
2358 .llseek = default_llseek,
2359};
2360
2361
2362/**
Lukasz Pawelczyk66867812014-03-11 17:07:06 +01002363 * smk_read_ptrace - read() for /smack/ptrace
2364 * @filp: file pointer, not actually used
2365 * @buf: where to put the result
2366 * @count: maximum to send along
2367 * @ppos: where to start
2368 *
2369 * Returns number of bytes read or error code, as appropriate
2370 */
2371static ssize_t smk_read_ptrace(struct file *filp, char __user *buf,
2372 size_t count, loff_t *ppos)
2373{
2374 char temp[32];
2375 ssize_t rc;
2376
2377 if (*ppos != 0)
2378 return 0;
2379
2380 sprintf(temp, "%d\n", smack_ptrace_rule);
2381 rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
2382 return rc;
2383}
2384
2385/**
2386 * smk_write_ptrace - write() for /smack/ptrace
2387 * @file: file pointer
2388 * @buf: data from user space
2389 * @count: bytes sent
2390 * @ppos: where to start - must be 0
2391 */
2392static ssize_t smk_write_ptrace(struct file *file, const char __user *buf,
2393 size_t count, loff_t *ppos)
2394{
2395 char temp[32];
2396 int i;
2397
2398 if (!smack_privileged(CAP_MAC_ADMIN))
2399 return -EPERM;
2400
2401 if (*ppos != 0 || count >= sizeof(temp) || count == 0)
2402 return -EINVAL;
2403
2404 if (copy_from_user(temp, buf, count) != 0)
2405 return -EFAULT;
2406
2407 temp[count] = '\0';
2408
2409 if (sscanf(temp, "%d", &i) != 1)
2410 return -EINVAL;
2411 if (i < SMACK_PTRACE_DEFAULT || i > SMACK_PTRACE_MAX)
2412 return -EINVAL;
2413 smack_ptrace_rule = i;
2414
2415 return count;
2416}
2417
2418static const struct file_operations smk_ptrace_ops = {
2419 .write = smk_write_ptrace,
2420 .read = smk_read_ptrace,
2421 .llseek = default_llseek,
2422};
2423
2424/**
Casey Schaufler00f84f32013-12-23 11:07:10 -08002425 * smk_fill_super - fill the smackfs superblock
Casey Schauflere114e472008-02-04 22:29:50 -08002426 * @sb: the empty superblock
2427 * @data: unused
2428 * @silent: unused
2429 *
Casey Schaufler00f84f32013-12-23 11:07:10 -08002430 * Fill in the well known entries for the smack filesystem
Casey Schauflere114e472008-02-04 22:29:50 -08002431 *
2432 * Returns 0 on success, an error code on failure
2433 */
2434static int smk_fill_super(struct super_block *sb, void *data, int silent)
2435{
2436 int rc;
2437 struct inode *root_inode;
2438
2439 static struct tree_descr smack_files[] = {
Casey Schaufler7898e1f2011-01-17 08:05:27 -08002440 [SMK_LOAD] = {
2441 "load", &smk_load_ops, S_IRUGO|S_IWUSR},
2442 [SMK_CIPSO] = {
2443 "cipso", &smk_cipso_ops, S_IRUGO|S_IWUSR},
2444 [SMK_DOI] = {
2445 "doi", &smk_doi_ops, S_IRUGO|S_IWUSR},
2446 [SMK_DIRECT] = {
2447 "direct", &smk_direct_ops, S_IRUGO|S_IWUSR},
2448 [SMK_AMBIENT] = {
2449 "ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR},
2450 [SMK_NETLBLADDR] = {
2451 "netlabel", &smk_netlbladdr_ops, S_IRUGO|S_IWUSR},
2452 [SMK_ONLYCAP] = {
2453 "onlycap", &smk_onlycap_ops, S_IRUGO|S_IWUSR},
2454 [SMK_LOGGING] = {
2455 "logging", &smk_logging_ops, S_IRUGO|S_IWUSR},
2456 [SMK_LOAD_SELF] = {
2457 "load-self", &smk_load_self_ops, S_IRUGO|S_IWUGO},
Jarkko Sakkinen828716c2011-09-08 10:12:01 +03002458 [SMK_ACCESSES] = {
Jarkko Sakkinen0e94ae12011-10-18 21:21:36 +03002459 "access", &smk_access_ops, S_IRUGO|S_IWUGO},
Casey Schauflerf7112e62012-05-06 15:22:02 -07002460 [SMK_MAPPED] = {
2461 "mapped", &smk_mapped_ops, S_IRUGO|S_IWUSR},
2462 [SMK_LOAD2] = {
2463 "load2", &smk_load2_ops, S_IRUGO|S_IWUSR},
2464 [SMK_LOAD_SELF2] = {
2465 "load-self2", &smk_load_self2_ops, S_IRUGO|S_IWUGO},
2466 [SMK_ACCESS2] = {
2467 "access2", &smk_access2_ops, S_IRUGO|S_IWUGO},
2468 [SMK_CIPSO2] = {
2469 "cipso2", &smk_cipso2_ops, S_IRUGO|S_IWUSR},
Rafal Krypa449543b2012-07-11 17:49:30 +02002470 [SMK_REVOKE_SUBJ] = {
2471 "revoke-subject", &smk_revoke_subj_ops,
2472 S_IRUGO|S_IWUSR},
Rafal Krypae05b6f92013-01-10 19:42:00 +01002473 [SMK_CHANGE_RULE] = {
2474 "change-rule", &smk_change_rule_ops, S_IRUGO|S_IWUSR},
Casey Schaufler00f84f32013-12-23 11:07:10 -08002475 [SMK_SYSLOG] = {
2476 "syslog", &smk_syslog_ops, S_IRUGO|S_IWUSR},
Lukasz Pawelczyk66867812014-03-11 17:07:06 +01002477 [SMK_PTRACE] = {
2478 "ptrace", &smk_ptrace_ops, S_IRUGO|S_IWUSR},
Casey Schauflerbf4b2fe2015-03-21 18:26:40 -07002479#ifdef CONFIG_SECURITY_SMACK_BRINGUP
2480 [SMK_UNCONFINED] = {
2481 "unconfined", &smk_unconfined_ops, S_IRUGO|S_IWUSR},
2482#endif
Casey Schaufler7898e1f2011-01-17 08:05:27 -08002483 /* last one */
2484 {""}
Casey Schauflere114e472008-02-04 22:29:50 -08002485 };
2486
2487 rc = simple_fill_super(sb, SMACK_MAGIC, smack_files);
2488 if (rc != 0) {
2489 printk(KERN_ERR "%s failed %d while creating inodes\n",
2490 __func__, rc);
2491 return rc;
2492 }
2493
2494 root_inode = sb->s_root->d_inode;
Casey Schauflere114e472008-02-04 22:29:50 -08002495
2496 return 0;
2497}
2498
2499/**
Al Virofc14f2f2010-07-25 01:48:30 +04002500 * smk_mount - get the smackfs superblock
Casey Schauflere114e472008-02-04 22:29:50 -08002501 * @fs_type: passed along without comment
2502 * @flags: passed along without comment
2503 * @dev_name: passed along without comment
2504 * @data: passed along without comment
Casey Schauflere114e472008-02-04 22:29:50 -08002505 *
2506 * Just passes everything along.
2507 *
2508 * Returns what the lower level code does.
2509 */
Al Virofc14f2f2010-07-25 01:48:30 +04002510static struct dentry *smk_mount(struct file_system_type *fs_type,
2511 int flags, const char *dev_name, void *data)
Casey Schauflere114e472008-02-04 22:29:50 -08002512{
Al Virofc14f2f2010-07-25 01:48:30 +04002513 return mount_single(fs_type, flags, data, smk_fill_super);
Casey Schauflere114e472008-02-04 22:29:50 -08002514}
2515
2516static struct file_system_type smk_fs_type = {
2517 .name = "smackfs",
Al Virofc14f2f2010-07-25 01:48:30 +04002518 .mount = smk_mount,
Casey Schauflere114e472008-02-04 22:29:50 -08002519 .kill_sb = kill_litter_super,
2520};
2521
2522static struct vfsmount *smackfs_mount;
2523
Casey Schauflerf7112e62012-05-06 15:22:02 -07002524static int __init smk_preset_netlabel(struct smack_known *skp)
2525{
2526 skp->smk_netlabel.domain = skp->smk_known;
2527 skp->smk_netlabel.flags =
2528 NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL;
2529 return smk_netlbl_mls(smack_cipso_direct, skp->smk_known,
2530 &skp->smk_netlabel, strlen(skp->smk_known));
2531}
2532
Casey Schauflere114e472008-02-04 22:29:50 -08002533/**
2534 * init_smk_fs - get the smackfs superblock
2535 *
2536 * register the smackfs
2537 *
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02002538 * Do not register smackfs if Smack wasn't enabled
2539 * on boot. We can not put this method normally under the
2540 * smack_init() code path since the security subsystem get
2541 * initialized before the vfs caches.
2542 *
2543 * Returns true if we were not chosen on boot or if
2544 * we were chosen and filesystem registration succeeded.
Casey Schauflere114e472008-02-04 22:29:50 -08002545 */
2546static int __init init_smk_fs(void)
2547{
2548 int err;
Casey Schauflerf7112e62012-05-06 15:22:02 -07002549 int rc;
Casey Schauflere114e472008-02-04 22:29:50 -08002550
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02002551 if (!security_module_enable(&smack_ops))
2552 return 0;
2553
Casey Schauflere9307232012-11-01 18:14:32 -07002554 err = smk_init_sysfs();
2555 if (err)
2556 printk(KERN_ERR "smackfs: sysfs mountpoint problem.\n");
2557
Casey Schauflere114e472008-02-04 22:29:50 -08002558 err = register_filesystem(&smk_fs_type);
2559 if (!err) {
2560 smackfs_mount = kern_mount(&smk_fs_type);
2561 if (IS_ERR(smackfs_mount)) {
2562 printk(KERN_ERR "smackfs: could not mount!\n");
2563 err = PTR_ERR(smackfs_mount);
2564 smackfs_mount = NULL;
2565 }
2566 }
2567
Casey Schauflere114e472008-02-04 22:29:50 -08002568 smk_cipso_doi();
Casey Schaufler4bc87e62008-02-15 15:24:25 -08002569 smk_unlbl_ambient(NULL);
Casey Schauflere114e472008-02-04 22:29:50 -08002570
Casey Schauflerf7112e62012-05-06 15:22:02 -07002571 rc = smk_preset_netlabel(&smack_known_floor);
2572 if (err == 0 && rc < 0)
2573 err = rc;
2574 rc = smk_preset_netlabel(&smack_known_hat);
2575 if (err == 0 && rc < 0)
2576 err = rc;
2577 rc = smk_preset_netlabel(&smack_known_huh);
2578 if (err == 0 && rc < 0)
2579 err = rc;
2580 rc = smk_preset_netlabel(&smack_known_invalid);
2581 if (err == 0 && rc < 0)
2582 err = rc;
2583 rc = smk_preset_netlabel(&smack_known_star);
2584 if (err == 0 && rc < 0)
2585 err = rc;
2586 rc = smk_preset_netlabel(&smack_known_web);
2587 if (err == 0 && rc < 0)
2588 err = rc;
2589
Casey Schauflere114e472008-02-04 22:29:50 -08002590 return err;
2591}
2592
2593__initcall(init_smk_fs);