blob: 47f73a0dabb1947abcd44c4e7ca946fcc1b62082 [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
Casey Schaufler21abb1e2015-07-22 14:25:31 -070032#define BEBITS (sizeof(__be32) * 8)
Casey Schauflere114e472008-02-04 22:29:50 -080033/*
34 * smackfs pseudo filesystem.
35 */
36
37enum smk_inos {
38 SMK_ROOT_INO = 2,
39 SMK_LOAD = 3, /* load policy */
40 SMK_CIPSO = 4, /* load label -> CIPSO mapping */
41 SMK_DOI = 5, /* CIPSO DOI */
42 SMK_DIRECT = 6, /* CIPSO level indicating direct label */
43 SMK_AMBIENT = 7, /* internet ambient label */
Casey Schaufler21abb1e2015-07-22 14:25:31 -070044 SMK_NET4ADDR = 8, /* single label hosts */
Casey Schaufler15446232008-07-30 15:37:11 -070045 SMK_ONLYCAP = 9, /* the only "capable" label */
Etienne Bassetecfcc532009-04-08 20:40:06 +020046 SMK_LOGGING = 10, /* logging */
Casey Schaufler7898e1f2011-01-17 08:05:27 -080047 SMK_LOAD_SELF = 11, /* task specific rules */
Jarkko Sakkinen828716c2011-09-08 10:12:01 +030048 SMK_ACCESSES = 12, /* access policy */
Casey Schauflerf7112e62012-05-06 15:22:02 -070049 SMK_MAPPED = 13, /* CIPSO level indicating mapped label */
50 SMK_LOAD2 = 14, /* load policy with long labels */
51 SMK_LOAD_SELF2 = 15, /* load task specific rules with long labels */
52 SMK_ACCESS2 = 16, /* make an access check with long labels */
53 SMK_CIPSO2 = 17, /* load long label -> CIPSO mapping */
Rafal Krypa449543b2012-07-11 17:49:30 +020054 SMK_REVOKE_SUBJ = 18, /* set rules with subject label to '-' */
Rafal Krypae05b6f92013-01-10 19:42:00 +010055 SMK_CHANGE_RULE = 19, /* change or add rules (long labels) */
Casey Schaufler00f84f32013-12-23 11:07:10 -080056 SMK_SYSLOG = 20, /* change syslog label) */
Lukasz Pawelczyk66867812014-03-11 17:07:06 +010057 SMK_PTRACE = 21, /* set ptrace rule */
Casey Schauflerbf4b2fe2015-03-21 18:26:40 -070058#ifdef CONFIG_SECURITY_SMACK_BRINGUP
59 SMK_UNCONFINED = 22, /* define an unconfined label */
60#endif
Casey Schaufler21abb1e2015-07-22 14:25:31 -070061#if IS_ENABLED(CONFIG_IPV6)
62 SMK_NET6ADDR = 23, /* single label IPv6 hosts */
63#endif /* CONFIG_IPV6 */
Zbigniew Jasinski38416e52015-10-19 18:23:53 +020064 SMK_RELABEL_SELF = 24, /* relabel possible without CAP_MAC_ADMIN */
Casey Schauflere114e472008-02-04 22:29:50 -080065};
66
67/*
68 * List locks
69 */
Casey Schauflere114e472008-02-04 22:29:50 -080070static DEFINE_MUTEX(smack_cipso_lock);
Casey Schaufler4bc87e62008-02-15 15:24:25 -080071static DEFINE_MUTEX(smack_ambient_lock);
Casey Schaufler21abb1e2015-07-22 14:25:31 -070072static DEFINE_MUTEX(smk_net4addr_lock);
73#if IS_ENABLED(CONFIG_IPV6)
74static DEFINE_MUTEX(smk_net6addr_lock);
75#endif /* CONFIG_IPV6 */
Casey Schauflere114e472008-02-04 22:29:50 -080076
77/*
78 * This is the "ambient" label for network traffic.
79 * If it isn't somehow marked, use this.
80 * It can be reset via smackfs/ambient
81 */
Casey Schaufler2f823ff2013-05-22 18:43:03 -070082struct smack_known *smack_net_ambient;
Casey Schauflere114e472008-02-04 22:29:50 -080083
84/*
Casey Schauflere114e472008-02-04 22:29:50 -080085 * This is the level in a CIPSO header that indicates a
86 * smack label is contained directly in the category set.
87 * It can be reset via smackfs/direct
88 */
89int smack_cipso_direct = SMACK_CIPSO_DIRECT_DEFAULT;
90
Casey Schaufler15446232008-07-30 15:37:11 -070091/*
Casey Schauflerf7112e62012-05-06 15:22:02 -070092 * This is the level in a CIPSO header that indicates a
93 * secid is contained directly in the category set.
94 * It can be reset via smackfs/mapped
95 */
96int smack_cipso_mapped = SMACK_CIPSO_MAPPED_DEFAULT;
97
Casey Schauflerbf4b2fe2015-03-21 18:26:40 -070098#ifdef CONFIG_SECURITY_SMACK_BRINGUP
99/*
100 * Allow one label to be unconfined. This is for
101 * debugging and application bring-up purposes only.
102 * It is bad and wrong, but everyone seems to expect
103 * to have it.
104 */
105struct smack_known *smack_unconfined;
106#endif
107
Casey Schaufler00f84f32013-12-23 11:07:10 -0800108/*
109 * If this value is set restrict syslog use to the label specified.
110 * It can be reset via smackfs/syslog
111 */
112struct smack_known *smack_syslog_label;
Casey Schaufler15446232008-07-30 15:37:11 -0700113
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500114/*
Lukasz Pawelczyk66867812014-03-11 17:07:06 +0100115 * Ptrace current rule
116 * SMACK_PTRACE_DEFAULT regular smack ptrace rules (/proc based)
117 * SMACK_PTRACE_EXACT labels must match, but can be overriden with
118 * CAP_SYS_PTRACE
119 * SMACK_PTRACE_DRACONIAN lables must match, CAP_SYS_PTRACE has no effect
120 */
121int smack_ptrace_rule = SMACK_PTRACE_DEFAULT;
122
123/*
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500124 * Certain IP addresses may be designated as single label hosts.
125 * Packets are sent there unlabeled, but only from tasks that
126 * can write to the specified label.
127 */
Etienne Basset7198e2e2009-03-24 20:53:24 +0100128
Casey Schaufler21abb1e2015-07-22 14:25:31 -0700129LIST_HEAD(smk_net4addr_list);
130#if IS_ENABLED(CONFIG_IPV6)
131LIST_HEAD(smk_net6addr_list);
132#endif /* CONFIG_IPV6 */
Casey Schaufler272cd7a2011-09-20 12:24:36 -0700133
134/*
135 * Rule lists are maintained for each label.
Casey Schaufler272cd7a2011-09-20 12:24:36 -0700136 */
Rafal Krypae05b6f92013-01-10 19:42:00 +0100137struct smack_parsed_rule {
Casey Schaufler2f823ff2013-05-22 18:43:03 -0700138 struct smack_known *smk_subject;
Lukasz Pawelczyk21c7eae2014-08-29 17:02:55 +0200139 struct smack_known *smk_object;
Rafal Krypae05b6f92013-01-10 19:42:00 +0100140 int smk_access1;
141 int smk_access2;
142};
143
Casey Schauflere114e472008-02-04 22:29:50 -0800144static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT;
Casey Schauflere114e472008-02-04 22:29:50 -0800145
Casey Schauflere114e472008-02-04 22:29:50 -0800146/*
Casey Schauflere114e472008-02-04 22:29:50 -0800147 * Values for parsing cipso rules
148 * SMK_DIGITLEN: Length of a digit field in a rule.
Ahmed S. Darwishb500ce82008-03-13 12:32:34 -0700149 * SMK_CIPSOMIN: Minimum possible cipso rule length.
150 * SMK_CIPSOMAX: Maximum possible cipso rule length.
Casey Schauflere114e472008-02-04 22:29:50 -0800151 */
152#define SMK_DIGITLEN 4
Ahmed S. Darwishb500ce82008-03-13 12:32:34 -0700153#define SMK_CIPSOMIN (SMK_LABELLEN + 2 * SMK_DIGITLEN)
154#define SMK_CIPSOMAX (SMK_CIPSOMIN + SMACK_CIPSO_MAXCATNUM * SMK_DIGITLEN)
155
156/*
157 * Values for parsing MAC rules
158 * SMK_ACCESS: Maximum possible combination of access permissions
159 * SMK_ACCESSLEN: Maximum length for a rule access field
160 * SMK_LOADLEN: Smack rule length
161 */
Jarkko Sakkinen5c6d1122010-12-07 13:34:01 +0200162#define SMK_OACCESS "rwxa"
Casey Schauflerc0ab6e52013-10-11 18:06:39 -0700163#define SMK_ACCESS "rwxatl"
Jarkko Sakkinen5c6d1122010-12-07 13:34:01 +0200164#define SMK_OACCESSLEN (sizeof(SMK_OACCESS) - 1)
165#define SMK_ACCESSLEN (sizeof(SMK_ACCESS) - 1)
166#define SMK_OLOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_OACCESSLEN)
167#define SMK_LOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_ACCESSLEN)
Ahmed S. Darwishb500ce82008-03-13 12:32:34 -0700168
Casey Schauflerf7112e62012-05-06 15:22:02 -0700169/*
170 * Stricly for CIPSO level manipulation.
171 * Set the category bit number in a smack label sized buffer.
172 */
173static inline void smack_catset_bit(unsigned int cat, char *catsetp)
174{
175 if (cat == 0 || cat > (SMK_CIPSOLEN * 8))
176 return;
177
178 catsetp[(cat - 1) / 8] |= 0x80 >> ((cat - 1) % 8);
179}
180
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500181/**
182 * smk_netlabel_audit_set - fill a netlbl_audit struct
183 * @nap: structure to fill
184 */
185static void smk_netlabel_audit_set(struct netlbl_audit *nap)
186{
Casey Schaufler2f823ff2013-05-22 18:43:03 -0700187 struct smack_known *skp = smk_of_current();
188
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500189 nap->loginuid = audit_get_loginuid(current);
190 nap->sessionid = audit_get_sessionid(current);
Casey Schaufler2f823ff2013-05-22 18:43:03 -0700191 nap->secid = skp->smk_secid;
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500192}
193
194/*
Casey Schauflerf7112e62012-05-06 15:22:02 -0700195 * Value for parsing single label host rules
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500196 * "1.2.3.4 X"
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500197 */
198#define SMK_NETLBLADDRMIN 9
Casey Schauflere114e472008-02-04 22:29:50 -0800199
Casey Schauflere114e472008-02-04 22:29:50 -0800200/**
Rafal Krypae05b6f92013-01-10 19:42:00 +0100201 * smk_set_access - add a rule to the rule list or replace an old rule
202 * @srp: the rule to add or replace
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800203 * @rule_list: the list of rules
204 * @rule_lock: the rule list lock
Casey Schauflere114e472008-02-04 22:29:50 -0800205 *
206 * Looks through the current subject/object/access list for
207 * the subject/object pair and replaces the access that was
208 * there. If the pair isn't found add it with the specified
209 * access.
Sergio Luis81ea7142008-12-22 01:16:15 -0300210 *
211 * Returns 0 if nothing goes wrong or -ENOMEM if it fails
212 * during the allocation of the new pair to add.
Casey Schauflere114e472008-02-04 22:29:50 -0800213 */
Rafal Krypae05b6f92013-01-10 19:42:00 +0100214static int smk_set_access(struct smack_parsed_rule *srp,
215 struct list_head *rule_list,
Vishal Goel460d95a2019-03-07 16:55:24 +0530216 struct mutex *rule_lock)
Casey Schauflere114e472008-02-04 22:29:50 -0800217{
Etienne Basset7198e2e2009-03-24 20:53:24 +0100218 struct smack_rule *sp;
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800219 int found = 0;
Rafal Krypae05b6f92013-01-10 19:42:00 +0100220 int rc = 0;
Casey Schauflere114e472008-02-04 22:29:50 -0800221
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800222 mutex_lock(rule_lock);
223
Casey Schaufler272cd7a2011-09-20 12:24:36 -0700224 /*
225 * Because the object label is less likely to match
226 * than the subject label check it first
227 */
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800228 list_for_each_entry_rcu(sp, rule_list, list) {
Casey Schaufler272cd7a2011-09-20 12:24:36 -0700229 if (sp->smk_object == srp->smk_object &&
230 sp->smk_subject == srp->smk_subject) {
Etienne Basset7198e2e2009-03-24 20:53:24 +0100231 found = 1;
Rafal Krypae05b6f92013-01-10 19:42:00 +0100232 sp->smk_access |= srp->smk_access1;
233 sp->smk_access &= ~srp->smk_access2;
Casey Schauflere114e472008-02-04 22:29:50 -0800234 break;
235 }
Casey Schauflere114e472008-02-04 22:29:50 -0800236 }
237
Rafal Krypae05b6f92013-01-10 19:42:00 +0100238 if (found == 0) {
Casey Schaufler4e328b02019-04-02 11:37:12 -0700239 sp = kmem_cache_zalloc(smack_rule_cache, GFP_KERNEL);
Rafal Krypae05b6f92013-01-10 19:42:00 +0100240 if (sp == NULL) {
241 rc = -ENOMEM;
242 goto out;
243 }
244
245 sp->smk_subject = srp->smk_subject;
246 sp->smk_object = srp->smk_object;
247 sp->smk_access = srp->smk_access1 & ~srp->smk_access2;
248
249 list_add_rcu(&sp->list, rule_list);
Rafal Krypae05b6f92013-01-10 19:42:00 +0100250 }
251
252out:
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800253 mutex_unlock(rule_lock);
Rafal Krypae05b6f92013-01-10 19:42:00 +0100254 return rc;
255}
Casey Schauflere114e472008-02-04 22:29:50 -0800256
Rafal Krypae05b6f92013-01-10 19:42:00 +0100257/**
258 * smk_perm_from_str - parse smack accesses from a text string
259 * @string: a text string that contains a Smack accesses code
260 *
261 * Returns an integer with respective bits set for specified accesses.
262 */
263static int smk_perm_from_str(const char *string)
264{
265 int perm = 0;
266 const char *cp;
267
268 for (cp = string; ; cp++)
269 switch (*cp) {
270 case '-':
271 break;
272 case 'r':
273 case 'R':
274 perm |= MAY_READ;
275 break;
276 case 'w':
277 case 'W':
278 perm |= MAY_WRITE;
279 break;
280 case 'x':
281 case 'X':
282 perm |= MAY_EXEC;
283 break;
284 case 'a':
285 case 'A':
286 perm |= MAY_APPEND;
287 break;
288 case 't':
289 case 'T':
290 perm |= MAY_TRANSMUTE;
291 break;
Casey Schauflerc0ab6e52013-10-11 18:06:39 -0700292 case 'l':
293 case 'L':
294 perm |= MAY_LOCK;
295 break;
Casey Schauflerd166c802014-08-27 14:51:27 -0700296 case 'b':
297 case 'B':
298 perm |= MAY_BRINGUP;
299 break;
Rafal Krypae05b6f92013-01-10 19:42:00 +0100300 default:
301 return perm;
302 }
Casey Schauflere114e472008-02-04 22:29:50 -0800303}
304
305/**
Casey Schauflerf7112e62012-05-06 15:22:02 -0700306 * smk_fill_rule - Fill Smack rule from strings
307 * @subject: subject label string
308 * @object: object label string
Rafal Krypae05b6f92013-01-10 19:42:00 +0100309 * @access1: access string
310 * @access2: string with permissions to be removed
Jarkko Sakkinen0e94ae12011-10-18 21:21:36 +0300311 * @rule: Smack rule
312 * @import: if non-zero, import labels
Casey Schaufler35187212012-06-18 19:01:36 -0700313 * @len: label length limit
Casey Schauflerf7112e62012-05-06 15:22:02 -0700314 *
Lukasz Pawelczyke774ad62015-04-20 17:12:54 +0200315 * Returns 0 on success, appropriate error code on failure.
Jarkko Sakkinen828716c2011-09-08 10:12:01 +0300316 */
Casey Schauflerf7112e62012-05-06 15:22:02 -0700317static int smk_fill_rule(const char *subject, const char *object,
Rafal Krypae05b6f92013-01-10 19:42:00 +0100318 const char *access1, const char *access2,
319 struct smack_parsed_rule *rule, int import,
320 int len)
Jarkko Sakkinen828716c2011-09-08 10:12:01 +0300321{
Casey Schauflerf7112e62012-05-06 15:22:02 -0700322 const char *cp;
Jarkko Sakkinen0e94ae12011-10-18 21:21:36 +0300323 struct smack_known *skp;
Jarkko Sakkinen828716c2011-09-08 10:12:01 +0300324
Jarkko Sakkinen0e94ae12011-10-18 21:21:36 +0300325 if (import) {
Casey Schaufler2f823ff2013-05-22 18:43:03 -0700326 rule->smk_subject = smk_import_entry(subject, len);
Lukasz Pawelczyke774ad62015-04-20 17:12:54 +0200327 if (IS_ERR(rule->smk_subject))
328 return PTR_ERR(rule->smk_subject);
Jarkko Sakkinen0e94ae12011-10-18 21:21:36 +0300329
Lukasz Pawelczyk21c7eae2014-08-29 17:02:55 +0200330 rule->smk_object = smk_import_entry(object, len);
Lukasz Pawelczyke774ad62015-04-20 17:12:54 +0200331 if (IS_ERR(rule->smk_object))
332 return PTR_ERR(rule->smk_object);
Jarkko Sakkinen0e94ae12011-10-18 21:21:36 +0300333 } else {
Casey Schaufler35187212012-06-18 19:01:36 -0700334 cp = smk_parse_smack(subject, len);
Lukasz Pawelczyke774ad62015-04-20 17:12:54 +0200335 if (IS_ERR(cp))
336 return PTR_ERR(cp);
Casey Schauflerf7112e62012-05-06 15:22:02 -0700337 skp = smk_find_entry(cp);
338 kfree(cp);
Jarkko Sakkinen0e94ae12011-10-18 21:21:36 +0300339 if (skp == NULL)
Jarkko Sakkinen398ce072013-11-28 19:16:46 +0200340 return -ENOENT;
Casey Schaufler2f823ff2013-05-22 18:43:03 -0700341 rule->smk_subject = skp;
Jarkko Sakkinen0e94ae12011-10-18 21:21:36 +0300342
Casey Schaufler35187212012-06-18 19:01:36 -0700343 cp = smk_parse_smack(object, len);
Lukasz Pawelczyke774ad62015-04-20 17:12:54 +0200344 if (IS_ERR(cp))
345 return PTR_ERR(cp);
Casey Schauflerf7112e62012-05-06 15:22:02 -0700346 skp = smk_find_entry(cp);
347 kfree(cp);
Jarkko Sakkinen0e94ae12011-10-18 21:21:36 +0300348 if (skp == NULL)
Jarkko Sakkinen398ce072013-11-28 19:16:46 +0200349 return -ENOENT;
Lukasz Pawelczyk21c7eae2014-08-29 17:02:55 +0200350 rule->smk_object = skp;
Jarkko Sakkinen0e94ae12011-10-18 21:21:36 +0300351 }
Jarkko Sakkinen828716c2011-09-08 10:12:01 +0300352
Rafal Krypae05b6f92013-01-10 19:42:00 +0100353 rule->smk_access1 = smk_perm_from_str(access1);
354 if (access2)
355 rule->smk_access2 = smk_perm_from_str(access2);
356 else
357 rule->smk_access2 = ~rule->smk_access1;
Jarkko Sakkinen828716c2011-09-08 10:12:01 +0300358
Casey Schaufler35187212012-06-18 19:01:36 -0700359 return 0;
Jarkko Sakkinen828716c2011-09-08 10:12:01 +0300360}
361
362/**
Casey Schauflerf7112e62012-05-06 15:22:02 -0700363 * smk_parse_rule - parse Smack rule from load string
364 * @data: string to be parsed whose size is SMK_LOADLEN
365 * @rule: Smack rule
366 * @import: if non-zero, import labels
367 *
368 * Returns 0 on success, -1 on errors.
369 */
Rafal Krypae05b6f92013-01-10 19:42:00 +0100370static int smk_parse_rule(const char *data, struct smack_parsed_rule *rule,
371 int import)
Casey Schauflerf7112e62012-05-06 15:22:02 -0700372{
373 int rc;
374
375 rc = smk_fill_rule(data, data + SMK_LABELLEN,
Rafal Krypae05b6f92013-01-10 19:42:00 +0100376 data + SMK_LABELLEN + SMK_LABELLEN, NULL, rule,
377 import, SMK_LABELLEN);
Casey Schauflerf7112e62012-05-06 15:22:02 -0700378 return rc;
379}
380
381/**
382 * smk_parse_long_rule - parse Smack rule from rule string
383 * @data: string to be parsed, null terminated
Rafal Krypae05b6f92013-01-10 19:42:00 +0100384 * @rule: Will be filled with Smack parsed rule
Casey Schauflerf7112e62012-05-06 15:22:02 -0700385 * @import: if non-zero, import labels
Rafal Krypa10289b02013-08-09 11:47:07 +0200386 * @tokens: numer of substrings expected in data
Casey Schauflerf7112e62012-05-06 15:22:02 -0700387 *
Lukasz Pawelczyke774ad62015-04-20 17:12:54 +0200388 * Returns number of processed bytes on success, -ERRNO on failure.
Casey Schauflerf7112e62012-05-06 15:22:02 -0700389 */
Rafal Krypa10289b02013-08-09 11:47:07 +0200390static ssize_t smk_parse_long_rule(char *data, struct smack_parsed_rule *rule,
391 int import, int tokens)
Casey Schauflerf7112e62012-05-06 15:22:02 -0700392{
Rafal Krypa10289b02013-08-09 11:47:07 +0200393 ssize_t cnt = 0;
394 char *tok[4];
Jarkko Sakkinen398ce072013-11-28 19:16:46 +0200395 int rc;
Rafal Krypa10289b02013-08-09 11:47:07 +0200396 int i;
Casey Schauflerf7112e62012-05-06 15:22:02 -0700397
Rafal Krypa10289b02013-08-09 11:47:07 +0200398 /*
399 * Parsing the rule in-place, filling all white-spaces with '\0'
400 */
401 for (i = 0; i < tokens; ++i) {
402 while (isspace(data[cnt]))
403 data[cnt++] = '\0';
Alan Cox3b9fc372012-07-26 14:47:11 -0700404
Rafal Krypa10289b02013-08-09 11:47:07 +0200405 if (data[cnt] == '\0')
406 /* Unexpected end of data */
Lukasz Pawelczyke774ad62015-04-20 17:12:54 +0200407 return -EINVAL;
Casey Schauflerf7112e62012-05-06 15:22:02 -0700408
Rafal Krypa10289b02013-08-09 11:47:07 +0200409 tok[i] = data + cnt;
410
411 while (data[cnt] && !isspace(data[cnt]))
412 ++cnt;
Rafal Krypae05b6f92013-01-10 19:42:00 +0100413 }
Rafal Krypa10289b02013-08-09 11:47:07 +0200414 while (isspace(data[cnt]))
415 data[cnt++] = '\0';
Casey Schauflerf7112e62012-05-06 15:22:02 -0700416
Rafal Krypa10289b02013-08-09 11:47:07 +0200417 while (i < 4)
418 tok[i++] = NULL;
419
Jarkko Sakkinen398ce072013-11-28 19:16:46 +0200420 rc = smk_fill_rule(tok[0], tok[1], tok[2], tok[3], rule, import, 0);
421 return rc == 0 ? cnt : rc;
Casey Schauflerf7112e62012-05-06 15:22:02 -0700422}
423
424#define SMK_FIXED24_FMT 0 /* Fixed 24byte label format */
425#define SMK_LONG_FMT 1 /* Variable long label format */
Rafal Krypae05b6f92013-01-10 19:42:00 +0100426#define SMK_CHANGE_FMT 2 /* Rule modification format */
Casey Schauflerf7112e62012-05-06 15:22:02 -0700427/**
428 * smk_write_rules_list - write() for any /smack rule file
Randy Dunlap251a2a92009-02-18 11:42:33 -0800429 * @file: file pointer, not actually used
Casey Schauflere114e472008-02-04 22:29:50 -0800430 * @buf: where to get the data from
431 * @count: bytes sent
432 * @ppos: where to start - must be 0
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800433 * @rule_list: the list of rules to write to
434 * @rule_lock: lock for the rule list
Rafal Krypae05b6f92013-01-10 19:42:00 +0100435 * @format: /smack/load or /smack/load2 or /smack/change-rule format.
Casey Schauflere114e472008-02-04 22:29:50 -0800436 *
437 * Get one smack access rule from above.
Casey Schauflerf7112e62012-05-06 15:22:02 -0700438 * The format for SMK_LONG_FMT is:
439 * "subject<whitespace>object<whitespace>access[<whitespace>...]"
440 * The format for SMK_FIXED24_FMT is exactly:
441 * "subject object rwxat"
Rafal Krypae05b6f92013-01-10 19:42:00 +0100442 * The format for SMK_CHANGE_FMT is:
443 * "subject<whitespace>object<whitespace>
444 * acc_enable<whitespace>acc_disable[<whitespace>...]"
Casey Schauflere114e472008-02-04 22:29:50 -0800445 */
Casey Schauflerf7112e62012-05-06 15:22:02 -0700446static ssize_t smk_write_rules_list(struct file *file, const char __user *buf,
447 size_t count, loff_t *ppos,
448 struct list_head *rule_list,
449 struct mutex *rule_lock, int format)
Casey Schauflere114e472008-02-04 22:29:50 -0800450{
Tomasz Stanislawski470043b2013-06-06 09:30:50 +0200451 struct smack_parsed_rule rule;
Casey Schauflere114e472008-02-04 22:29:50 -0800452 char *data;
Rafal Krypa10289b02013-08-09 11:47:07 +0200453 int rc;
454 int trunc = 0;
455 int tokens;
456 ssize_t cnt = 0;
Casey Schauflere114e472008-02-04 22:29:50 -0800457
458 /*
Casey Schauflere114e472008-02-04 22:29:50 -0800459 * No partial writes.
460 * Enough data must be present.
461 */
Jarkko Sakkinen5c6d1122010-12-07 13:34:01 +0200462 if (*ppos != 0)
463 return -EINVAL;
Casey Schauflere114e472008-02-04 22:29:50 -0800464
Casey Schauflerf7112e62012-05-06 15:22:02 -0700465 if (format == SMK_FIXED24_FMT) {
466 /*
467 * Minor hack for backward compatibility
468 */
Casey Schauflerc0ab6e52013-10-11 18:06:39 -0700469 if (count < SMK_OLOADLEN || count > SMK_LOADLEN)
Casey Schauflerf7112e62012-05-06 15:22:02 -0700470 return -EINVAL;
Rafal Krypa10289b02013-08-09 11:47:07 +0200471 } else {
472 if (count >= PAGE_SIZE) {
473 count = PAGE_SIZE - 1;
474 trunc = 1;
475 }
476 }
Casey Schauflerf7112e62012-05-06 15:22:02 -0700477
Al Viro16e5c1f2015-12-24 00:06:05 -0500478 data = memdup_user_nul(buf, count);
479 if (IS_ERR(data))
480 return PTR_ERR(data);
Casey Schauflere114e472008-02-04 22:29:50 -0800481
Rafal Krypa10289b02013-08-09 11:47:07 +0200482 /*
483 * In case of parsing only part of user buf,
484 * avoid having partial rule at the data buffer
485 */
486 if (trunc) {
487 while (count > 0 && (data[count - 1] != '\n'))
488 --count;
489 if (count == 0) {
490 rc = -EINVAL;
Tomasz Stanislawski470043b2013-06-06 09:30:50 +0200491 goto out;
Rafal Krypa10289b02013-08-09 11:47:07 +0200492 }
493 }
494
495 data[count] = '\0';
496 tokens = (format == SMK_CHANGE_FMT ? 4 : 3);
497 while (cnt < count) {
498 if (format == SMK_FIXED24_FMT) {
499 rc = smk_parse_rule(data, &rule, 1);
Lukasz Pawelczyke774ad62015-04-20 17:12:54 +0200500 if (rc < 0)
Rafal Krypa10289b02013-08-09 11:47:07 +0200501 goto out;
Rafal Krypa10289b02013-08-09 11:47:07 +0200502 cnt = count;
503 } else {
504 rc = smk_parse_long_rule(data + cnt, &rule, 1, tokens);
Lukasz Pawelczyke774ad62015-04-20 17:12:54 +0200505 if (rc < 0)
506 goto out;
507 if (rc == 0) {
Rafal Krypa10289b02013-08-09 11:47:07 +0200508 rc = -EINVAL;
509 goto out;
510 }
511 cnt += rc;
512 }
513
514 if (rule_list == NULL)
515 rc = smk_set_access(&rule, &rule.smk_subject->smk_rules,
Vishal Goel460d95a2019-03-07 16:55:24 +0530516 &rule.smk_subject->smk_rules_lock);
Rafal Krypa10289b02013-08-09 11:47:07 +0200517 else
Vishal Goel460d95a2019-03-07 16:55:24 +0530518 rc = smk_set_access(&rule, rule_list, rule_lock);
Rafal Krypa10289b02013-08-09 11:47:07 +0200519
520 if (rc)
Tomasz Stanislawski470043b2013-06-06 09:30:50 +0200521 goto out;
Casey Schauflerf7112e62012-05-06 15:22:02 -0700522 }
523
Rafal Krypa10289b02013-08-09 11:47:07 +0200524 rc = cnt;
Casey Schauflere114e472008-02-04 22:29:50 -0800525out:
526 kfree(data);
527 return rc;
528}
529
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800530/*
Casey Schaufler40809562011-11-10 15:02:22 -0800531 * Core logic for smackfs seq list operations.
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800532 */
533
Casey Schaufler40809562011-11-10 15:02:22 -0800534static void *smk_seq_start(struct seq_file *s, loff_t *pos,
535 struct list_head *head)
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800536{
Casey Schaufler272cd7a2011-09-20 12:24:36 -0700537 struct list_head *list;
Rafal Krypa01fa8472015-05-21 18:24:31 +0200538 int i = *pos;
Casey Schaufler272cd7a2011-09-20 12:24:36 -0700539
Rafal Krypa01fa8472015-05-21 18:24:31 +0200540 rcu_read_lock();
541 for (list = rcu_dereference(list_next_rcu(head));
542 list != head;
543 list = rcu_dereference(list_next_rcu(list))) {
544 if (i-- == 0)
545 return list;
546 }
Casey Schaufler272cd7a2011-09-20 12:24:36 -0700547
Rafal Krypa01fa8472015-05-21 18:24:31 +0200548 return NULL;
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800549}
550
Casey Schaufler40809562011-11-10 15:02:22 -0800551static void *smk_seq_next(struct seq_file *s, void *v, loff_t *pos,
552 struct list_head *head)
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800553{
554 struct list_head *list = v;
555
Rafal Krypa01fa8472015-05-21 18:24:31 +0200556 ++*pos;
557 list = rcu_dereference(list_next_rcu(list));
558
559 return (list == head) ? NULL : list;
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800560}
561
Casey Schaufler40809562011-11-10 15:02:22 -0800562static void smk_seq_stop(struct seq_file *s, void *v)
563{
Rafal Krypa01fa8472015-05-21 18:24:31 +0200564 rcu_read_unlock();
Casey Schaufler40809562011-11-10 15:02:22 -0800565}
566
Casey Schauflerf7112e62012-05-06 15:22:02 -0700567static void smk_rule_show(struct seq_file *s, struct smack_rule *srp, int max)
Casey Schaufler40809562011-11-10 15:02:22 -0800568{
Casey Schauflerf7112e62012-05-06 15:22:02 -0700569 /*
570 * Don't show any rules with label names too long for
571 * interface file (/smack/load or /smack/load2)
572 * because you should expect to be able to write
573 * anything you read back.
574 */
Casey Schaufler2f823ff2013-05-22 18:43:03 -0700575 if (strlen(srp->smk_subject->smk_known) >= max ||
Lukasz Pawelczyk21c7eae2014-08-29 17:02:55 +0200576 strlen(srp->smk_object->smk_known) >= max)
Casey Schauflerf7112e62012-05-06 15:22:02 -0700577 return;
Casey Schaufler40809562011-11-10 15:02:22 -0800578
Rafal Krypa65ee7f42012-07-09 19:36:34 +0200579 if (srp->smk_access == 0)
580 return;
581
Lukasz Pawelczyk21c7eae2014-08-29 17:02:55 +0200582 seq_printf(s, "%s %s",
583 srp->smk_subject->smk_known,
584 srp->smk_object->smk_known);
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800585
586 seq_putc(s, ' ');
587
588 if (srp->smk_access & MAY_READ)
589 seq_putc(s, 'r');
590 if (srp->smk_access & MAY_WRITE)
591 seq_putc(s, 'w');
592 if (srp->smk_access & MAY_EXEC)
593 seq_putc(s, 'x');
594 if (srp->smk_access & MAY_APPEND)
595 seq_putc(s, 'a');
596 if (srp->smk_access & MAY_TRANSMUTE)
597 seq_putc(s, 't');
Casey Schauflerc0ab6e52013-10-11 18:06:39 -0700598 if (srp->smk_access & MAY_LOCK)
599 seq_putc(s, 'l');
Casey Schauflerd166c802014-08-27 14:51:27 -0700600 if (srp->smk_access & MAY_BRINGUP)
601 seq_putc(s, 'b');
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800602
603 seq_putc(s, '\n');
Casey Schauflerf7112e62012-05-06 15:22:02 -0700604}
605
606/*
607 * Seq_file read operations for /smack/load
608 */
609
610static void *load2_seq_start(struct seq_file *s, loff_t *pos)
611{
Vishal Goel460d95a2019-03-07 16:55:24 +0530612 return smk_seq_start(s, pos, &smack_known_list);
Casey Schauflerf7112e62012-05-06 15:22:02 -0700613}
614
615static void *load2_seq_next(struct seq_file *s, void *v, loff_t *pos)
616{
Vishal Goel460d95a2019-03-07 16:55:24 +0530617 return smk_seq_next(s, v, pos, &smack_known_list);
Casey Schauflerf7112e62012-05-06 15:22:02 -0700618}
619
620static int load_seq_show(struct seq_file *s, void *v)
621{
622 struct list_head *list = v;
Vishal Goel460d95a2019-03-07 16:55:24 +0530623 struct smack_rule *srp;
624 struct smack_known *skp =
625 list_entry_rcu(list, struct smack_known, list);
Casey Schauflerf7112e62012-05-06 15:22:02 -0700626
Vishal Goel460d95a2019-03-07 16:55:24 +0530627 list_for_each_entry_rcu(srp, &skp->smk_rules, list)
628 smk_rule_show(s, srp, SMK_LABELLEN);
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800629
630 return 0;
631}
632
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800633static const struct seq_operations load_seq_ops = {
Casey Schauflerf7112e62012-05-06 15:22:02 -0700634 .start = load2_seq_start,
635 .next = load2_seq_next,
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800636 .show = load_seq_show,
Casey Schaufler40809562011-11-10 15:02:22 -0800637 .stop = smk_seq_stop,
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800638};
639
640/**
641 * smk_open_load - open() for /smack/load
642 * @inode: inode structure representing file
643 * @file: "load" file pointer
644 *
645 * For reading, use load_seq_* seq_file reading operations.
646 */
647static int smk_open_load(struct inode *inode, struct file *file)
648{
649 return seq_open(file, &load_seq_ops);
650}
651
652/**
653 * smk_write_load - write() for /smack/load
654 * @file: file pointer, not actually used
655 * @buf: where to get the data from
656 * @count: bytes sent
657 * @ppos: where to start - must be 0
658 *
659 */
660static ssize_t smk_write_load(struct file *file, const char __user *buf,
661 size_t count, loff_t *ppos)
662{
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800663 /*
664 * Must have privilege.
665 * No partial writes.
666 * Enough data must be present.
667 */
Casey Schaufler1880eff2012-06-05 15:28:30 -0700668 if (!smack_privileged(CAP_MAC_ADMIN))
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800669 return -EPERM;
670
Casey Schauflerf7112e62012-05-06 15:22:02 -0700671 return smk_write_rules_list(file, buf, count, ppos, NULL, NULL,
672 SMK_FIXED24_FMT);
Casey Schaufler7898e1f2011-01-17 08:05:27 -0800673}
674
Casey Schauflere114e472008-02-04 22:29:50 -0800675static const struct file_operations smk_load_ops = {
676 .open = smk_open_load,
677 .read = seq_read,
678 .llseek = seq_lseek,
679 .write = smk_write_load,
Ahmed S. Darwishcb622bb2008-03-24 12:29:49 -0700680 .release = seq_release,
Casey Schauflere114e472008-02-04 22:29:50 -0800681};
682
683/**
684 * smk_cipso_doi - initialize the CIPSO domain
685 */
Casey Schaufler30aa4fa2008-04-28 02:13:43 -0700686static void smk_cipso_doi(void)
Casey Schauflere114e472008-02-04 22:29:50 -0800687{
688 int rc;
689 struct cipso_v4_doi *doip;
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500690 struct netlbl_audit nai;
Casey Schauflere114e472008-02-04 22:29:50 -0800691
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500692 smk_netlabel_audit_set(&nai);
Casey Schaufler4bc87e62008-02-15 15:24:25 -0800693
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500694 rc = netlbl_cfg_map_del(NULL, PF_INET, NULL, NULL, &nai);
Casey Schauflere114e472008-02-04 22:29:50 -0800695 if (rc != 0)
696 printk(KERN_WARNING "%s:%d remove rc = %d\n",
697 __func__, __LINE__, rc);
698
699 doip = kmalloc(sizeof(struct cipso_v4_doi), GFP_KERNEL);
700 if (doip == NULL)
701 panic("smack: Failed to initialize cipso DOI.\n");
702 doip->map.std = NULL;
703 doip->doi = smk_cipso_doi_value;
704 doip->type = CIPSO_V4_MAP_PASS;
705 doip->tags[0] = CIPSO_V4_TAG_RBITMAP;
706 for (rc = 1; rc < CIPSO_V4_TAG_MAXCNT; rc++)
707 doip->tags[rc] = CIPSO_V4_TAG_INVALID;
708
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500709 rc = netlbl_cfg_cipsov4_add(doip, &nai);
Paul Mooreb1edeb12008-10-10 10:16:31 -0400710 if (rc != 0) {
Paul Moore6c2e8ac2008-12-31 12:54:11 -0500711 printk(KERN_WARNING "%s:%d cipso add rc = %d\n",
Casey Schauflere114e472008-02-04 22:29:50 -0800712 __func__, __LINE__, rc);
Paul Mooreb1edeb12008-10-10 10:16:31 -0400713 kfree(doip);
Paul Moore6c2e8ac2008-12-31 12:54:11 -0500714 return;
715 }
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500716 rc = netlbl_cfg_cipsov4_map_add(doip->doi, NULL, NULL, NULL, &nai);
Paul Moore6c2e8ac2008-12-31 12:54:11 -0500717 if (rc != 0) {
718 printk(KERN_WARNING "%s:%d map add rc = %d\n",
719 __func__, __LINE__, rc);
720 kfree(doip);
721 return;
Paul Mooreb1edeb12008-10-10 10:16:31 -0400722 }
Casey Schauflere114e472008-02-04 22:29:50 -0800723}
724
Casey Schaufler4bc87e62008-02-15 15:24:25 -0800725/**
726 * smk_unlbl_ambient - initialize the unlabeled domain
Randy Dunlap251a2a92009-02-18 11:42:33 -0800727 * @oldambient: previous domain string
Casey Schaufler4bc87e62008-02-15 15:24:25 -0800728 */
Casey Schaufler30aa4fa2008-04-28 02:13:43 -0700729static void smk_unlbl_ambient(char *oldambient)
Casey Schaufler4bc87e62008-02-15 15:24:25 -0800730{
731 int rc;
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500732 struct netlbl_audit nai;
Casey Schaufler4bc87e62008-02-15 15:24:25 -0800733
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500734 smk_netlabel_audit_set(&nai);
Casey Schaufler4bc87e62008-02-15 15:24:25 -0800735
736 if (oldambient != NULL) {
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500737 rc = netlbl_cfg_map_del(oldambient, PF_INET, NULL, NULL, &nai);
Casey Schaufler4bc87e62008-02-15 15:24:25 -0800738 if (rc != 0)
739 printk(KERN_WARNING "%s:%d remove rc = %d\n",
740 __func__, __LINE__, rc);
741 }
Casey Schauflerf7112e62012-05-06 15:22:02 -0700742 if (smack_net_ambient == NULL)
Casey Schaufler2f823ff2013-05-22 18:43:03 -0700743 smack_net_ambient = &smack_known_floor;
Casey Schaufler4bc87e62008-02-15 15:24:25 -0800744
Casey Schaufler2f823ff2013-05-22 18:43:03 -0700745 rc = netlbl_cfg_unlbl_map_add(smack_net_ambient->smk_known, PF_INET,
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500746 NULL, NULL, &nai);
Casey Schaufler4bc87e62008-02-15 15:24:25 -0800747 if (rc != 0)
748 printk(KERN_WARNING "%s:%d add rc = %d\n",
749 __func__, __LINE__, rc);
750}
751
Casey Schauflere114e472008-02-04 22:29:50 -0800752/*
753 * Seq_file read operations for /smack/cipso
754 */
755
756static void *cipso_seq_start(struct seq_file *s, loff_t *pos)
757{
Casey Schaufler40809562011-11-10 15:02:22 -0800758 return smk_seq_start(s, pos, &smack_known_list);
Casey Schauflere114e472008-02-04 22:29:50 -0800759}
760
761static void *cipso_seq_next(struct seq_file *s, void *v, loff_t *pos)
762{
Casey Schaufler40809562011-11-10 15:02:22 -0800763 return smk_seq_next(s, v, pos, &smack_known_list);
Casey Schauflere114e472008-02-04 22:29:50 -0800764}
765
766/*
767 * Print cipso labels in format:
768 * label level[/cat[,cat]]
769 */
770static int cipso_seq_show(struct seq_file *s, void *v)
771{
Etienne Basset7198e2e2009-03-24 20:53:24 +0100772 struct list_head *list = v;
773 struct smack_known *skp =
Rafal Krypa01fa8472015-05-21 18:24:31 +0200774 list_entry_rcu(list, struct smack_known, list);
Paul Moore4fbe63d2014-08-01 11:17:37 -0400775 struct netlbl_lsm_catmap *cmp = skp->smk_netlabel.attr.mls.cat;
Casey Schauflere114e472008-02-04 22:29:50 -0800776 char sep = '/';
Casey Schauflere114e472008-02-04 22:29:50 -0800777 int i;
Casey Schauflere114e472008-02-04 22:29:50 -0800778
Casey Schauflerf7112e62012-05-06 15:22:02 -0700779 /*
780 * Don't show a label that could not have been set using
781 * /smack/cipso. This is in support of the notion that
782 * anything read from /smack/cipso ought to be writeable
783 * to /smack/cipso.
784 *
785 * /smack/cipso2 should be used instead.
786 */
787 if (strlen(skp->smk_known) >= SMK_LABELLEN)
Casey Schauflere114e472008-02-04 22:29:50 -0800788 return 0;
789
Casey Schauflerf7112e62012-05-06 15:22:02 -0700790 seq_printf(s, "%s %3d", skp->smk_known, skp->smk_netlabel.attr.mls.lvl);
Casey Schauflere114e472008-02-04 22:29:50 -0800791
Paul Moore4fbe63d2014-08-01 11:17:37 -0400792 for (i = netlbl_catmap_walk(cmp, 0); i >= 0;
793 i = netlbl_catmap_walk(cmp, i + 1)) {
Casey Schauflerf7112e62012-05-06 15:22:02 -0700794 seq_printf(s, "%c%d", sep, i);
795 sep = ',';
796 }
Casey Schauflere114e472008-02-04 22:29:50 -0800797
798 seq_putc(s, '\n');
799
800 return 0;
801}
802
James Morris88e9d342009-09-22 16:43:43 -0700803static const struct seq_operations cipso_seq_ops = {
Casey Schauflere114e472008-02-04 22:29:50 -0800804 .start = cipso_seq_start,
Casey Schauflere114e472008-02-04 22:29:50 -0800805 .next = cipso_seq_next,
806 .show = cipso_seq_show,
Casey Schaufler40809562011-11-10 15:02:22 -0800807 .stop = smk_seq_stop,
Casey Schauflere114e472008-02-04 22:29:50 -0800808};
809
810/**
811 * smk_open_cipso - open() for /smack/cipso
812 * @inode: inode structure representing file
813 * @file: "cipso" file pointer
814 *
815 * Connect our cipso_seq_* operations with /smack/cipso
816 * file_operations
817 */
818static int smk_open_cipso(struct inode *inode, struct file *file)
819{
820 return seq_open(file, &cipso_seq_ops);
821}
822
823/**
Casey Schauflerf7112e62012-05-06 15:22:02 -0700824 * smk_set_cipso - do the work for write() for cipso and cipso2
Randy Dunlap251a2a92009-02-18 11:42:33 -0800825 * @file: file pointer, not actually used
Casey Schauflere114e472008-02-04 22:29:50 -0800826 * @buf: where to get the data from
827 * @count: bytes sent
828 * @ppos: where to start
Casey Schauflerf7112e62012-05-06 15:22:02 -0700829 * @format: /smack/cipso or /smack/cipso2
Casey Schauflere114e472008-02-04 22:29:50 -0800830 *
831 * Accepts only one cipso rule per write call.
832 * Returns number of bytes written or error code, as appropriate
833 */
Casey Schauflerf7112e62012-05-06 15:22:02 -0700834static ssize_t smk_set_cipso(struct file *file, const char __user *buf,
835 size_t count, loff_t *ppos, int format)
Casey Schauflere114e472008-02-04 22:29:50 -0800836{
837 struct smack_known *skp;
Casey Schauflerf7112e62012-05-06 15:22:02 -0700838 struct netlbl_lsm_secattr ncats;
839 char mapcatset[SMK_CIPSOLEN];
Casey Schauflere114e472008-02-04 22:29:50 -0800840 int maplevel;
Casey Schauflerf7112e62012-05-06 15:22:02 -0700841 unsigned int cat;
Casey Schauflere114e472008-02-04 22:29:50 -0800842 int catlen;
843 ssize_t rc = -EINVAL;
844 char *data = NULL;
845 char *rule;
846 int ret;
847 int i;
848
849 /*
850 * Must have privilege.
851 * No partial writes.
852 * Enough data must be present.
853 */
Casey Schaufler1880eff2012-06-05 15:28:30 -0700854 if (!smack_privileged(CAP_MAC_ADMIN))
Casey Schauflere114e472008-02-04 22:29:50 -0800855 return -EPERM;
856 if (*ppos != 0)
857 return -EINVAL;
Casey Schauflerf7112e62012-05-06 15:22:02 -0700858 if (format == SMK_FIXED24_FMT &&
859 (count < SMK_CIPSOMIN || count > SMK_CIPSOMAX))
Casey Schauflere114e472008-02-04 22:29:50 -0800860 return -EINVAL;
861
Al Viro16e5c1f2015-12-24 00:06:05 -0500862 data = memdup_user_nul(buf, count);
863 if (IS_ERR(data))
864 return PTR_ERR(data);
Casey Schauflere114e472008-02-04 22:29:50 -0800865
Casey Schauflere114e472008-02-04 22:29:50 -0800866 rule = data;
867 /*
868 * Only allow one writer at a time. Writes should be
869 * quite rare and small in any case.
870 */
871 mutex_lock(&smack_cipso_lock);
872
873 skp = smk_import_entry(rule, 0);
Lukasz Pawelczyke774ad62015-04-20 17:12:54 +0200874 if (IS_ERR(skp)) {
875 rc = PTR_ERR(skp);
Casey Schauflere114e472008-02-04 22:29:50 -0800876 goto out;
Lukasz Pawelczyke774ad62015-04-20 17:12:54 +0200877 }
Casey Schauflere114e472008-02-04 22:29:50 -0800878
Casey Schauflerf7112e62012-05-06 15:22:02 -0700879 if (format == SMK_FIXED24_FMT)
880 rule += SMK_LABELLEN;
881 else
Passion,Zhao0fcfee62013-06-03 11:42:24 +0800882 rule += strlen(skp->smk_known) + 1;
Casey Schauflerf7112e62012-05-06 15:22:02 -0700883
Casey Schauflere114e472008-02-04 22:29:50 -0800884 ret = sscanf(rule, "%d", &maplevel);
885 if (ret != 1 || maplevel > SMACK_CIPSO_MAXLEVEL)
886 goto out;
887
888 rule += SMK_DIGITLEN;
889 ret = sscanf(rule, "%d", &catlen);
890 if (ret != 1 || catlen > SMACK_CIPSO_MAXCATNUM)
891 goto out;
892
Casey Schauflerf7112e62012-05-06 15:22:02 -0700893 if (format == SMK_FIXED24_FMT &&
894 count != (SMK_CIPSOMIN + catlen * SMK_DIGITLEN))
Casey Schauflere114e472008-02-04 22:29:50 -0800895 goto out;
896
897 memset(mapcatset, 0, sizeof(mapcatset));
898
899 for (i = 0; i < catlen; i++) {
900 rule += SMK_DIGITLEN;
Casey Schauflerf7112e62012-05-06 15:22:02 -0700901 ret = sscanf(rule, "%u", &cat);
Casey Schaufler677264e2013-06-28 13:47:07 -0700902 if (ret != 1 || cat > SMACK_CIPSO_MAXCATNUM)
Casey Schauflere114e472008-02-04 22:29:50 -0800903 goto out;
904
905 smack_catset_bit(cat, mapcatset);
906 }
907
Casey Schauflerf7112e62012-05-06 15:22:02 -0700908 rc = smk_netlbl_mls(maplevel, mapcatset, &ncats, SMK_CIPSOLEN);
909 if (rc >= 0) {
Paul Moore4fbe63d2014-08-01 11:17:37 -0400910 netlbl_catmap_free(skp->smk_netlabel.attr.mls.cat);
Casey Schauflerf7112e62012-05-06 15:22:02 -0700911 skp->smk_netlabel.attr.mls.cat = ncats.attr.mls.cat;
912 skp->smk_netlabel.attr.mls.lvl = ncats.attr.mls.lvl;
913 rc = count;
Casey Schauflere114e472008-02-04 22:29:50 -0800914 }
915
Casey Schauflere114e472008-02-04 22:29:50 -0800916out:
917 mutex_unlock(&smack_cipso_lock);
Casey Schauflere114e472008-02-04 22:29:50 -0800918 kfree(data);
919 return rc;
920}
921
Casey Schauflerf7112e62012-05-06 15:22:02 -0700922/**
923 * smk_write_cipso - write() for /smack/cipso
924 * @file: file pointer, not actually used
925 * @buf: where to get the data from
926 * @count: bytes sent
927 * @ppos: where to start
928 *
929 * Accepts only one cipso rule per write call.
930 * Returns number of bytes written or error code, as appropriate
931 */
932static ssize_t smk_write_cipso(struct file *file, const char __user *buf,
933 size_t count, loff_t *ppos)
934{
935 return smk_set_cipso(file, buf, count, ppos, SMK_FIXED24_FMT);
936}
937
Casey Schauflere114e472008-02-04 22:29:50 -0800938static const struct file_operations smk_cipso_ops = {
939 .open = smk_open_cipso,
940 .read = seq_read,
941 .llseek = seq_lseek,
942 .write = smk_write_cipso,
943 .release = seq_release,
944};
945
Casey Schaufler6d3dc072008-12-31 12:54:12 -0500946/*
Casey Schauflerf7112e62012-05-06 15:22:02 -0700947 * Seq_file read operations for /smack/cipso2
948 */
949
950/*
951 * Print cipso labels in format:
952 * label level[/cat[,cat]]
953 */
954static int cipso2_seq_show(struct seq_file *s, void *v)
955{
956 struct list_head *list = v;
957 struct smack_known *skp =
Rafal Krypa01fa8472015-05-21 18:24:31 +0200958 list_entry_rcu(list, struct smack_known, list);
Paul Moore4fbe63d2014-08-01 11:17:37 -0400959 struct netlbl_lsm_catmap *cmp = skp->smk_netlabel.attr.mls.cat;
Casey Schauflerf7112e62012-05-06 15:22:02 -0700960 char sep = '/';
961 int i;
962
963 seq_printf(s, "%s %3d", skp->smk_known, skp->smk_netlabel.attr.mls.lvl);
964
Paul Moore4fbe63d2014-08-01 11:17:37 -0400965 for (i = netlbl_catmap_walk(cmp, 0); i >= 0;
966 i = netlbl_catmap_walk(cmp, i + 1)) {
Casey Schauflerf7112e62012-05-06 15:22:02 -0700967 seq_printf(s, "%c%d", sep, i);
968 sep = ',';
969 }
970
971 seq_putc(s, '\n');
972
973 return 0;
974}
975
976static const struct seq_operations cipso2_seq_ops = {
977 .start = cipso_seq_start,
978 .next = cipso_seq_next,
979 .show = cipso2_seq_show,
980 .stop = smk_seq_stop,
981};
982
983/**
984 * smk_open_cipso2 - open() for /smack/cipso2
985 * @inode: inode structure representing file
986 * @file: "cipso2" file pointer
987 *
988 * Connect our cipso_seq_* operations with /smack/cipso2
989 * file_operations
990 */
991static int smk_open_cipso2(struct inode *inode, struct file *file)
992{
993 return seq_open(file, &cipso2_seq_ops);
994}
995
996/**
997 * smk_write_cipso2 - write() for /smack/cipso2
998 * @file: file pointer, not actually used
999 * @buf: where to get the data from
1000 * @count: bytes sent
1001 * @ppos: where to start
1002 *
1003 * Accepts only one cipso rule per write call.
1004 * Returns number of bytes written or error code, as appropriate
1005 */
1006static ssize_t smk_write_cipso2(struct file *file, const char __user *buf,
1007 size_t count, loff_t *ppos)
1008{
1009 return smk_set_cipso(file, buf, count, ppos, SMK_LONG_FMT);
1010}
1011
1012static const struct file_operations smk_cipso2_ops = {
1013 .open = smk_open_cipso2,
1014 .read = seq_read,
1015 .llseek = seq_lseek,
1016 .write = smk_write_cipso2,
1017 .release = seq_release,
1018};
1019
1020/*
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001021 * Seq_file read operations for /smack/netlabel
1022 */
1023
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001024static void *net4addr_seq_start(struct seq_file *s, loff_t *pos)
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001025{
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001026 return smk_seq_start(s, pos, &smk_net4addr_list);
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001027}
1028
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001029static void *net4addr_seq_next(struct seq_file *s, void *v, loff_t *pos)
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001030{
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001031 return smk_seq_next(s, v, pos, &smk_net4addr_list);
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001032}
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001033
1034/*
1035 * Print host/label pairs
1036 */
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001037static int net4addr_seq_show(struct seq_file *s, void *v)
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001038{
Etienne Basset7198e2e2009-03-24 20:53:24 +01001039 struct list_head *list = v;
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001040 struct smk_net4addr *skp =
1041 list_entry_rcu(list, struct smk_net4addr, list);
1042 char *kp = SMACK_CIPSO_OPTION;
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001043
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001044 if (skp->smk_label != NULL)
1045 kp = skp->smk_label->smk_known;
1046 seq_printf(s, "%pI4/%d %s\n", &skp->smk_host.s_addr,
1047 skp->smk_masks, kp);
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001048
1049 return 0;
1050}
1051
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001052static const struct seq_operations net4addr_seq_ops = {
1053 .start = net4addr_seq_start,
1054 .next = net4addr_seq_next,
1055 .show = net4addr_seq_show,
Casey Schaufler40809562011-11-10 15:02:22 -08001056 .stop = smk_seq_stop,
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001057};
1058
1059/**
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001060 * smk_open_net4addr - open() for /smack/netlabel
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001061 * @inode: inode structure representing file
1062 * @file: "netlabel" file pointer
1063 *
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001064 * Connect our net4addr_seq_* operations with /smack/netlabel
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001065 * file_operations
1066 */
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001067static int smk_open_net4addr(struct inode *inode, struct file *file)
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001068{
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001069 return seq_open(file, &net4addr_seq_ops);
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001070}
1071
1072/**
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001073 * smk_net4addr_insert
etienne113a0e42009-03-04 07:33:51 +01001074 * @new : netlabel to insert
1075 *
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001076 * This helper insert netlabel in the smack_net4addrs list
etienne113a0e42009-03-04 07:33:51 +01001077 * sorted by netmask length (longest to smallest)
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001078 * locked by &smk_net4addr_lock in smk_write_net4addr
Etienne Basset7198e2e2009-03-24 20:53:24 +01001079 *
etienne113a0e42009-03-04 07:33:51 +01001080 */
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001081static void smk_net4addr_insert(struct smk_net4addr *new)
etienne113a0e42009-03-04 07:33:51 +01001082{
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001083 struct smk_net4addr *m;
1084 struct smk_net4addr *m_next;
etienne113a0e42009-03-04 07:33:51 +01001085
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001086 if (list_empty(&smk_net4addr_list)) {
1087 list_add_rcu(&new->list, &smk_net4addr_list);
etienne113a0e42009-03-04 07:33:51 +01001088 return;
1089 }
1090
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001091 m = list_entry_rcu(smk_net4addr_list.next,
1092 struct smk_net4addr, list);
Etienne Basset7198e2e2009-03-24 20:53:24 +01001093
etienne113a0e42009-03-04 07:33:51 +01001094 /* the comparison '>' is a bit hacky, but works */
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001095 if (new->smk_masks > m->smk_masks) {
1096 list_add_rcu(&new->list, &smk_net4addr_list);
etienne113a0e42009-03-04 07:33:51 +01001097 return;
1098 }
Etienne Basset7198e2e2009-03-24 20:53:24 +01001099
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001100 list_for_each_entry_rcu(m, &smk_net4addr_list, list) {
1101 if (list_is_last(&m->list, &smk_net4addr_list)) {
Etienne Basset7198e2e2009-03-24 20:53:24 +01001102 list_add_rcu(&new->list, &m->list);
etienne113a0e42009-03-04 07:33:51 +01001103 return;
1104 }
Jiri Pirko05725f72009-04-14 20:17:16 +02001105 m_next = list_entry_rcu(m->list.next,
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001106 struct smk_net4addr, list);
1107 if (new->smk_masks > m_next->smk_masks) {
Etienne Basset7198e2e2009-03-24 20:53:24 +01001108 list_add_rcu(&new->list, &m->list);
etienne113a0e42009-03-04 07:33:51 +01001109 return;
1110 }
1111 }
1112}
1113
1114
1115/**
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001116 * smk_write_net4addr - write() for /smack/netlabel
Randy Dunlap251a2a92009-02-18 11:42:33 -08001117 * @file: file pointer, not actually used
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001118 * @buf: where to get the data from
1119 * @count: bytes sent
1120 * @ppos: where to start
1121 *
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001122 * Accepts only one net4addr per write call.
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001123 * Returns number of bytes written or error code, as appropriate
1124 */
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001125static ssize_t smk_write_net4addr(struct file *file, const char __user *buf,
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001126 size_t count, loff_t *ppos)
1127{
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001128 struct smk_net4addr *snp;
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001129 struct sockaddr_in newname;
Casey Schauflerf7112e62012-05-06 15:22:02 -07001130 char *smack;
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001131 struct smack_known *skp = NULL;
Casey Schauflerf7112e62012-05-06 15:22:02 -07001132 char *data;
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001133 char *host = (char *)&newname.sin_addr.s_addr;
1134 int rc;
1135 struct netlbl_audit audit_info;
1136 struct in_addr mask;
1137 unsigned int m;
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001138 unsigned int masks;
Etienne Basset7198e2e2009-03-24 20:53:24 +01001139 int found;
etienne113a0e42009-03-04 07:33:51 +01001140 u32 mask_bits = (1<<31);
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001141 __be32 nsa;
etienne113a0e42009-03-04 07:33:51 +01001142 u32 temp_mask;
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001143
1144 /*
1145 * Must have privilege.
1146 * No partial writes.
1147 * Enough data must be present.
1148 * "<addr/mask, as a.b.c.d/e><space><label>"
1149 * "<addr, as a.b.c.d><space><label>"
1150 */
Casey Schaufler1880eff2012-06-05 15:28:30 -07001151 if (!smack_privileged(CAP_MAC_ADMIN))
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001152 return -EPERM;
1153 if (*ppos != 0)
1154 return -EINVAL;
Casey Schauflerf7112e62012-05-06 15:22:02 -07001155 if (count < SMK_NETLBLADDRMIN)
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001156 return -EINVAL;
Casey Schauflerf7112e62012-05-06 15:22:02 -07001157
Al Viro16e5c1f2015-12-24 00:06:05 -05001158 data = memdup_user_nul(buf, count);
1159 if (IS_ERR(data))
1160 return PTR_ERR(data);
Casey Schauflerf7112e62012-05-06 15:22:02 -07001161
1162 smack = kzalloc(count + 1, GFP_KERNEL);
1163 if (smack == NULL) {
1164 rc = -ENOMEM;
1165 goto free_data_out;
1166 }
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001167
Toralf Försterec554fa2014-04-27 19:33:34 +02001168 rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd/%u %s",
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001169 &host[0], &host[1], &host[2], &host[3], &masks, smack);
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001170 if (rc != 6) {
1171 rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd %s",
1172 &host[0], &host[1], &host[2], &host[3], smack);
Casey Schauflerf7112e62012-05-06 15:22:02 -07001173 if (rc != 5) {
1174 rc = -EINVAL;
1175 goto free_out;
1176 }
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001177 m = BEBITS;
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001178 masks = 32;
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001179 }
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001180 if (masks > BEBITS) {
Casey Schauflerf7112e62012-05-06 15:22:02 -07001181 rc = -EINVAL;
1182 goto free_out;
1183 }
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001184
Casey Schauflerf7112e62012-05-06 15:22:02 -07001185 /*
1186 * If smack begins with '-', it is an option, don't import it
1187 */
Etienne Basset43031542009-03-27 17:11:01 -04001188 if (smack[0] != '-') {
Lukasz Pawelczyk21c7eae2014-08-29 17:02:55 +02001189 skp = smk_import_entry(smack, 0);
Lukasz Pawelczyke774ad62015-04-20 17:12:54 +02001190 if (IS_ERR(skp)) {
1191 rc = PTR_ERR(skp);
Casey Schauflerf7112e62012-05-06 15:22:02 -07001192 goto free_out;
1193 }
Etienne Basset43031542009-03-27 17:11:01 -04001194 } else {
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001195 /*
1196 * Only the -CIPSO option is supported for IPv4
1197 */
1198 if (strcmp(smack, SMACK_CIPSO_OPTION) != 0) {
Casey Schauflerf7112e62012-05-06 15:22:02 -07001199 rc = -EINVAL;
1200 goto free_out;
1201 }
Etienne Basset43031542009-03-27 17:11:01 -04001202 }
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001203
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001204 for (m = masks, temp_mask = 0; m > 0; m--) {
etienne113a0e42009-03-04 07:33:51 +01001205 temp_mask |= mask_bits;
1206 mask_bits >>= 1;
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001207 }
etienne113a0e42009-03-04 07:33:51 +01001208 mask.s_addr = cpu_to_be32(temp_mask);
1209
1210 newname.sin_addr.s_addr &= mask.s_addr;
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001211 /*
1212 * Only allow one writer at a time. Writes should be
1213 * quite rare and small in any case.
1214 */
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001215 mutex_lock(&smk_net4addr_lock);
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001216
1217 nsa = newname.sin_addr.s_addr;
etienne113a0e42009-03-04 07:33:51 +01001218 /* try to find if the prefix is already in the list */
Etienne Basset7198e2e2009-03-24 20:53:24 +01001219 found = 0;
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001220 list_for_each_entry_rcu(snp, &smk_net4addr_list, list) {
1221 if (snp->smk_host.s_addr == nsa && snp->smk_masks == masks) {
Etienne Basset7198e2e2009-03-24 20:53:24 +01001222 found = 1;
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001223 break;
Etienne Basset7198e2e2009-03-24 20:53:24 +01001224 }
1225 }
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001226 smk_netlabel_audit_set(&audit_info);
1227
Etienne Basset7198e2e2009-03-24 20:53:24 +01001228 if (found == 0) {
Lukasz Pawelczyk21c7eae2014-08-29 17:02:55 +02001229 snp = kzalloc(sizeof(*snp), GFP_KERNEL);
1230 if (snp == NULL)
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001231 rc = -ENOMEM;
1232 else {
1233 rc = 0;
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001234 snp->smk_host.s_addr = newname.sin_addr.s_addr;
Lukasz Pawelczyk21c7eae2014-08-29 17:02:55 +02001235 snp->smk_mask.s_addr = mask.s_addr;
1236 snp->smk_label = skp;
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001237 snp->smk_masks = masks;
1238 smk_net4addr_insert(snp);
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001239 }
1240 } else {
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001241 /*
1242 * Delete the unlabeled entry, only if the previous label
1243 * wasn't the special CIPSO option
1244 */
1245 if (snp->smk_label != NULL)
Etienne Basset43031542009-03-27 17:11:01 -04001246 rc = netlbl_cfg_unlbl_static_del(&init_net, NULL,
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001247 &snp->smk_host, &snp->smk_mask,
Etienne Basset43031542009-03-27 17:11:01 -04001248 PF_INET, &audit_info);
1249 else
1250 rc = 0;
Lukasz Pawelczyk21c7eae2014-08-29 17:02:55 +02001251 snp->smk_label = skp;
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001252 }
1253
1254 /*
1255 * Now tell netlabel about the single label nature of
1256 * this host so that incoming packets get labeled.
Etienne Basset43031542009-03-27 17:11:01 -04001257 * but only if we didn't get the special CIPSO option
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001258 */
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001259 if (rc == 0 && skp != NULL)
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001260 rc = netlbl_cfg_unlbl_static_add(&init_net, NULL,
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001261 &snp->smk_host, &snp->smk_mask, PF_INET,
Lukasz Pawelczyk21c7eae2014-08-29 17:02:55 +02001262 snp->smk_label->smk_secid, &audit_info);
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001263
1264 if (rc == 0)
1265 rc = count;
1266
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001267 mutex_unlock(&smk_net4addr_lock);
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001268
Casey Schauflerf7112e62012-05-06 15:22:02 -07001269free_out:
1270 kfree(smack);
1271free_data_out:
1272 kfree(data);
1273
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001274 return rc;
1275}
1276
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001277static const struct file_operations smk_net4addr_ops = {
1278 .open = smk_open_net4addr,
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001279 .read = seq_read,
1280 .llseek = seq_lseek,
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001281 .write = smk_write_net4addr,
Casey Schaufler6d3dc072008-12-31 12:54:12 -05001282 .release = seq_release,
1283};
1284
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001285#if IS_ENABLED(CONFIG_IPV6)
1286/*
1287 * Seq_file read operations for /smack/netlabel6
1288 */
1289
1290static void *net6addr_seq_start(struct seq_file *s, loff_t *pos)
1291{
1292 return smk_seq_start(s, pos, &smk_net6addr_list);
1293}
1294
1295static void *net6addr_seq_next(struct seq_file *s, void *v, loff_t *pos)
1296{
1297 return smk_seq_next(s, v, pos, &smk_net6addr_list);
1298}
1299
1300/*
1301 * Print host/label pairs
1302 */
1303static int net6addr_seq_show(struct seq_file *s, void *v)
1304{
1305 struct list_head *list = v;
1306 struct smk_net6addr *skp =
1307 list_entry(list, struct smk_net6addr, list);
1308
1309 if (skp->smk_label != NULL)
1310 seq_printf(s, "%pI6/%d %s\n", &skp->smk_host, skp->smk_masks,
1311 skp->smk_label->smk_known);
1312
1313 return 0;
1314}
1315
1316static const struct seq_operations net6addr_seq_ops = {
1317 .start = net6addr_seq_start,
1318 .next = net6addr_seq_next,
1319 .show = net6addr_seq_show,
1320 .stop = smk_seq_stop,
1321};
1322
1323/**
1324 * smk_open_net6addr - open() for /smack/netlabel
1325 * @inode: inode structure representing file
1326 * @file: "netlabel" file pointer
1327 *
1328 * Connect our net6addr_seq_* operations with /smack/netlabel
1329 * file_operations
1330 */
1331static int smk_open_net6addr(struct inode *inode, struct file *file)
1332{
1333 return seq_open(file, &net6addr_seq_ops);
1334}
1335
1336/**
1337 * smk_net6addr_insert
1338 * @new : entry to insert
1339 *
1340 * This inserts an entry in the smack_net6addrs list
1341 * sorted by netmask length (longest to smallest)
1342 * locked by &smk_net6addr_lock in smk_write_net6addr
1343 *
1344 */
1345static void smk_net6addr_insert(struct smk_net6addr *new)
1346{
1347 struct smk_net6addr *m_next;
1348 struct smk_net6addr *m;
1349
1350 if (list_empty(&smk_net6addr_list)) {
1351 list_add_rcu(&new->list, &smk_net6addr_list);
1352 return;
1353 }
1354
1355 m = list_entry_rcu(smk_net6addr_list.next,
1356 struct smk_net6addr, list);
1357
1358 if (new->smk_masks > m->smk_masks) {
1359 list_add_rcu(&new->list, &smk_net6addr_list);
1360 return;
1361 }
1362
1363 list_for_each_entry_rcu(m, &smk_net6addr_list, list) {
1364 if (list_is_last(&m->list, &smk_net6addr_list)) {
1365 list_add_rcu(&new->list, &m->list);
1366 return;
1367 }
1368 m_next = list_entry_rcu(m->list.next,
1369 struct smk_net6addr, list);
1370 if (new->smk_masks > m_next->smk_masks) {
1371 list_add_rcu(&new->list, &m->list);
1372 return;
1373 }
1374 }
1375}
1376
1377
1378/**
1379 * smk_write_net6addr - write() for /smack/netlabel
1380 * @file: file pointer, not actually used
1381 * @buf: where to get the data from
1382 * @count: bytes sent
1383 * @ppos: where to start
1384 *
1385 * Accepts only one net6addr per write call.
1386 * Returns number of bytes written or error code, as appropriate
1387 */
1388static ssize_t smk_write_net6addr(struct file *file, const char __user *buf,
1389 size_t count, loff_t *ppos)
1390{
1391 struct smk_net6addr *snp;
1392 struct in6_addr newname;
1393 struct in6_addr fullmask;
1394 struct smack_known *skp = NULL;
1395 char *smack;
1396 char *data;
1397 int rc = 0;
1398 int found = 0;
1399 int i;
1400 unsigned int scanned[8];
1401 unsigned int m;
1402 unsigned int mask = 128;
1403
1404 /*
1405 * Must have privilege.
1406 * No partial writes.
1407 * Enough data must be present.
1408 * "<addr/mask, as a:b:c:d:e:f:g:h/e><space><label>"
1409 * "<addr, as a:b:c:d:e:f:g:h><space><label>"
1410 */
1411 if (!smack_privileged(CAP_MAC_ADMIN))
1412 return -EPERM;
1413 if (*ppos != 0)
1414 return -EINVAL;
1415 if (count < SMK_NETLBLADDRMIN)
1416 return -EINVAL;
1417
Al Viro16e5c1f2015-12-24 00:06:05 -05001418 data = memdup_user_nul(buf, count);
1419 if (IS_ERR(data))
1420 return PTR_ERR(data);
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001421
1422 smack = kzalloc(count + 1, GFP_KERNEL);
1423 if (smack == NULL) {
1424 rc = -ENOMEM;
1425 goto free_data_out;
1426 }
1427
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001428 i = sscanf(data, "%x:%x:%x:%x:%x:%x:%x:%x/%u %s",
1429 &scanned[0], &scanned[1], &scanned[2], &scanned[3],
1430 &scanned[4], &scanned[5], &scanned[6], &scanned[7],
1431 &mask, smack);
1432 if (i != 10) {
1433 i = sscanf(data, "%x:%x:%x:%x:%x:%x:%x:%x %s",
1434 &scanned[0], &scanned[1], &scanned[2],
1435 &scanned[3], &scanned[4], &scanned[5],
1436 &scanned[6], &scanned[7], smack);
1437 if (i != 9) {
1438 rc = -EINVAL;
1439 goto free_out;
1440 }
1441 }
1442 if (mask > 128) {
1443 rc = -EINVAL;
1444 goto free_out;
1445 }
1446 for (i = 0; i < 8; i++) {
1447 if (scanned[i] > 0xffff) {
1448 rc = -EINVAL;
1449 goto free_out;
1450 }
1451 newname.s6_addr16[i] = htons(scanned[i]);
1452 }
1453
1454 /*
1455 * If smack begins with '-', it is an option, don't import it
1456 */
1457 if (smack[0] != '-') {
1458 skp = smk_import_entry(smack, 0);
Lukasz Pawelczyk5f2bfe22015-08-25 12:39:46 +02001459 if (IS_ERR(skp)) {
1460 rc = PTR_ERR(skp);
Casey Schaufler21abb1e2015-07-22 14:25:31 -07001461 goto free_out;
1462 }
1463 } else {
1464 /*
1465 * Only -DELETE is supported for IPv6
1466 */
1467 if (strcmp(smack, SMACK_DELETE_OPTION) != 0) {
1468 rc = -EINVAL;
1469 goto free_out;
1470 }
1471 }
1472
1473 for (i = 0, m = mask; i < 8; i++) {
1474 if (m >= 16) {
1475 fullmask.s6_addr16[i] = 0xffff;
1476 m -= 16;
1477 } else if (m > 0) {
1478 fullmask.s6_addr16[i] = (1 << m) - 1;
1479 m = 0;
1480 } else
1481 fullmask.s6_addr16[i] = 0;
1482 newname.s6_addr16[i] &= fullmask.s6_addr16[i];
1483 }
1484
1485 /*
1486 * Only allow one writer at a time. Writes should be
1487 * quite rare and small in any case.
1488 */
1489 mutex_lock(&smk_net6addr_lock);
1490 /*
1491 * Try to find the prefix in the list
1492 */
1493 list_for_each_entry_rcu(snp, &smk_net6addr_list, list) {
1494 if (mask != snp->smk_masks)
1495 continue;
1496 for (found = 1, i = 0; i < 8; i++) {
1497 if (newname.s6_addr16[i] !=
1498 snp->smk_host.s6_addr16[i]) {
1499 found = 0;
1500 break;
1501 }
1502 }
1503 if (found == 1)
1504 break;
1505 }
1506 if (found == 0) {
1507 snp = kzalloc(sizeof(*snp), GFP_KERNEL);
1508 if (snp == NULL)
1509 rc = -ENOMEM;
1510 else {
1511 snp->smk_host = newname;
1512 snp->smk_mask = fullmask;
1513 snp->smk_masks = mask;
1514 snp->smk_label = skp;
1515 smk_net6addr_insert(snp);
1516 }
1517 } else {
1518 snp->smk_label = skp;
1519 }
1520
1521 if (rc == 0)
1522 rc = count;
1523
1524 mutex_unlock(&smk_net6addr_lock);
1525
1526free_out:
1527 kfree(smack);
1528free_data_out:
1529 kfree(data);
1530
1531 return rc;
1532}
1533
1534static const struct file_operations smk_net6addr_ops = {
1535 .open = smk_open_net6addr,
1536 .read = seq_read,
1537 .llseek = seq_lseek,
1538 .write = smk_write_net6addr,
1539 .release = seq_release,
1540};
1541#endif /* CONFIG_IPV6 */
1542
Casey Schauflere114e472008-02-04 22:29:50 -08001543/**
1544 * smk_read_doi - read() for /smack/doi
1545 * @filp: file pointer, not actually used
1546 * @buf: where to put the result
1547 * @count: maximum to send along
1548 * @ppos: where to start
1549 *
1550 * Returns number of bytes read or error code, as appropriate
1551 */
1552static ssize_t smk_read_doi(struct file *filp, char __user *buf,
1553 size_t count, loff_t *ppos)
1554{
1555 char temp[80];
1556 ssize_t rc;
1557
1558 if (*ppos != 0)
1559 return 0;
1560
1561 sprintf(temp, "%d", smk_cipso_doi_value);
1562 rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
1563
1564 return rc;
1565}
1566
1567/**
1568 * smk_write_doi - write() for /smack/doi
Randy Dunlap251a2a92009-02-18 11:42:33 -08001569 * @file: file pointer, not actually used
Casey Schauflere114e472008-02-04 22:29:50 -08001570 * @buf: where to get the data from
1571 * @count: bytes sent
1572 * @ppos: where to start
1573 *
1574 * Returns number of bytes written or error code, as appropriate
1575 */
1576static ssize_t smk_write_doi(struct file *file, const char __user *buf,
1577 size_t count, loff_t *ppos)
1578{
1579 char temp[80];
1580 int i;
1581
Casey Schaufler1880eff2012-06-05 15:28:30 -07001582 if (!smack_privileged(CAP_MAC_ADMIN))
Casey Schauflere114e472008-02-04 22:29:50 -08001583 return -EPERM;
1584
1585 if (count >= sizeof(temp) || count == 0)
1586 return -EINVAL;
1587
1588 if (copy_from_user(temp, buf, count) != 0)
1589 return -EFAULT;
1590
1591 temp[count] = '\0';
1592
1593 if (sscanf(temp, "%d", &i) != 1)
1594 return -EINVAL;
1595
1596 smk_cipso_doi_value = i;
1597
1598 smk_cipso_doi();
1599
1600 return count;
1601}
1602
1603static const struct file_operations smk_doi_ops = {
1604 .read = smk_read_doi,
1605 .write = smk_write_doi,
Arnd Bergmann6038f372010-08-15 18:52:59 +02001606 .llseek = default_llseek,
Casey Schauflere114e472008-02-04 22:29:50 -08001607};
1608
1609/**
1610 * smk_read_direct - read() for /smack/direct
1611 * @filp: file pointer, not actually used
1612 * @buf: where to put the result
1613 * @count: maximum to send along
1614 * @ppos: where to start
1615 *
1616 * Returns number of bytes read or error code, as appropriate
1617 */
1618static ssize_t smk_read_direct(struct file *filp, char __user *buf,
1619 size_t count, loff_t *ppos)
1620{
1621 char temp[80];
1622 ssize_t rc;
1623
1624 if (*ppos != 0)
1625 return 0;
1626
1627 sprintf(temp, "%d", smack_cipso_direct);
1628 rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
1629
1630 return rc;
1631}
1632
1633/**
1634 * smk_write_direct - write() for /smack/direct
Randy Dunlap251a2a92009-02-18 11:42:33 -08001635 * @file: file pointer, not actually used
Casey Schauflere114e472008-02-04 22:29:50 -08001636 * @buf: where to get the data from
1637 * @count: bytes sent
1638 * @ppos: where to start
1639 *
1640 * Returns number of bytes written or error code, as appropriate
1641 */
1642static ssize_t smk_write_direct(struct file *file, const char __user *buf,
1643 size_t count, loff_t *ppos)
1644{
Casey Schauflerf7112e62012-05-06 15:22:02 -07001645 struct smack_known *skp;
Casey Schauflere114e472008-02-04 22:29:50 -08001646 char temp[80];
1647 int i;
1648
Casey Schaufler1880eff2012-06-05 15:28:30 -07001649 if (!smack_privileged(CAP_MAC_ADMIN))
Casey Schauflere114e472008-02-04 22:29:50 -08001650 return -EPERM;
1651
1652 if (count >= sizeof(temp) || count == 0)
1653 return -EINVAL;
1654
1655 if (copy_from_user(temp, buf, count) != 0)
1656 return -EFAULT;
1657
1658 temp[count] = '\0';
1659
1660 if (sscanf(temp, "%d", &i) != 1)
1661 return -EINVAL;
1662
Casey Schauflerf7112e62012-05-06 15:22:02 -07001663 /*
1664 * Don't do anything if the value hasn't actually changed.
1665 * If it is changing reset the level on entries that were
1666 * set up to be direct when they were created.
1667 */
1668 if (smack_cipso_direct != i) {
1669 mutex_lock(&smack_known_lock);
1670 list_for_each_entry_rcu(skp, &smack_known_list, list)
1671 if (skp->smk_netlabel.attr.mls.lvl ==
1672 smack_cipso_direct)
1673 skp->smk_netlabel.attr.mls.lvl = i;
1674 smack_cipso_direct = i;
1675 mutex_unlock(&smack_known_lock);
1676 }
Casey Schauflere114e472008-02-04 22:29:50 -08001677
1678 return count;
1679}
1680
1681static const struct file_operations smk_direct_ops = {
1682 .read = smk_read_direct,
1683 .write = smk_write_direct,
Arnd Bergmann6038f372010-08-15 18:52:59 +02001684 .llseek = default_llseek,
Casey Schauflere114e472008-02-04 22:29:50 -08001685};
1686
1687/**
Casey Schauflerf7112e62012-05-06 15:22:02 -07001688 * smk_read_mapped - read() for /smack/mapped
1689 * @filp: file pointer, not actually used
1690 * @buf: where to put the result
1691 * @count: maximum to send along
1692 * @ppos: where to start
1693 *
1694 * Returns number of bytes read or error code, as appropriate
1695 */
1696static ssize_t smk_read_mapped(struct file *filp, char __user *buf,
1697 size_t count, loff_t *ppos)
1698{
1699 char temp[80];
1700 ssize_t rc;
1701
1702 if (*ppos != 0)
1703 return 0;
1704
1705 sprintf(temp, "%d", smack_cipso_mapped);
1706 rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
1707
1708 return rc;
1709}
1710
1711/**
1712 * smk_write_mapped - write() for /smack/mapped
1713 * @file: file pointer, not actually used
1714 * @buf: where to get the data from
1715 * @count: bytes sent
1716 * @ppos: where to start
1717 *
1718 * Returns number of bytes written or error code, as appropriate
1719 */
1720static ssize_t smk_write_mapped(struct file *file, const char __user *buf,
1721 size_t count, loff_t *ppos)
1722{
1723 struct smack_known *skp;
1724 char temp[80];
1725 int i;
1726
Casey Schaufler1880eff2012-06-05 15:28:30 -07001727 if (!smack_privileged(CAP_MAC_ADMIN))
Casey Schauflerf7112e62012-05-06 15:22:02 -07001728 return -EPERM;
1729
1730 if (count >= sizeof(temp) || count == 0)
1731 return -EINVAL;
1732
1733 if (copy_from_user(temp, buf, count) != 0)
1734 return -EFAULT;
1735
1736 temp[count] = '\0';
1737
1738 if (sscanf(temp, "%d", &i) != 1)
1739 return -EINVAL;
1740
1741 /*
1742 * Don't do anything if the value hasn't actually changed.
1743 * If it is changing reset the level on entries that were
1744 * set up to be mapped when they were created.
1745 */
1746 if (smack_cipso_mapped != i) {
1747 mutex_lock(&smack_known_lock);
1748 list_for_each_entry_rcu(skp, &smack_known_list, list)
1749 if (skp->smk_netlabel.attr.mls.lvl ==
1750 smack_cipso_mapped)
1751 skp->smk_netlabel.attr.mls.lvl = i;
1752 smack_cipso_mapped = i;
1753 mutex_unlock(&smack_known_lock);
1754 }
1755
1756 return count;
1757}
1758
1759static const struct file_operations smk_mapped_ops = {
1760 .read = smk_read_mapped,
1761 .write = smk_write_mapped,
1762 .llseek = default_llseek,
1763};
1764
1765/**
Casey Schauflere114e472008-02-04 22:29:50 -08001766 * smk_read_ambient - read() for /smack/ambient
1767 * @filp: file pointer, not actually used
1768 * @buf: where to put the result
1769 * @cn: maximum to send along
1770 * @ppos: where to start
1771 *
1772 * Returns number of bytes read or error code, as appropriate
1773 */
1774static ssize_t smk_read_ambient(struct file *filp, char __user *buf,
1775 size_t cn, loff_t *ppos)
1776{
1777 ssize_t rc;
Casey Schauflere114e472008-02-04 22:29:50 -08001778 int asize;
1779
1780 if (*ppos != 0)
1781 return 0;
1782 /*
1783 * Being careful to avoid a problem in the case where
1784 * smack_net_ambient gets changed in midstream.
Casey Schauflere114e472008-02-04 22:29:50 -08001785 */
Casey Schaufler4bc87e62008-02-15 15:24:25 -08001786 mutex_lock(&smack_ambient_lock);
Casey Schauflere114e472008-02-04 22:29:50 -08001787
Casey Schaufler2f823ff2013-05-22 18:43:03 -07001788 asize = strlen(smack_net_ambient->smk_known) + 1;
Casey Schauflere114e472008-02-04 22:29:50 -08001789
Casey Schaufler4bc87e62008-02-15 15:24:25 -08001790 if (cn >= asize)
1791 rc = simple_read_from_buffer(buf, cn, ppos,
Casey Schaufler2f823ff2013-05-22 18:43:03 -07001792 smack_net_ambient->smk_known,
1793 asize);
Casey Schaufler4bc87e62008-02-15 15:24:25 -08001794 else
1795 rc = -EINVAL;
1796
1797 mutex_unlock(&smack_ambient_lock);
Casey Schauflere114e472008-02-04 22:29:50 -08001798
1799 return rc;
1800}
1801
1802/**
1803 * smk_write_ambient - write() for /smack/ambient
Randy Dunlap251a2a92009-02-18 11:42:33 -08001804 * @file: file pointer, not actually used
Casey Schauflere114e472008-02-04 22:29:50 -08001805 * @buf: where to get the data from
1806 * @count: bytes sent
1807 * @ppos: where to start
1808 *
1809 * Returns number of bytes written or error code, as appropriate
1810 */
1811static ssize_t smk_write_ambient(struct file *file, const char __user *buf,
1812 size_t count, loff_t *ppos)
1813{
Casey Schaufler2f823ff2013-05-22 18:43:03 -07001814 struct smack_known *skp;
Casey Schaufler4bc87e62008-02-15 15:24:25 -08001815 char *oldambient;
Casey Schauflerf7112e62012-05-06 15:22:02 -07001816 char *data;
1817 int rc = count;
Casey Schauflere114e472008-02-04 22:29:50 -08001818
Casey Schaufler1880eff2012-06-05 15:28:30 -07001819 if (!smack_privileged(CAP_MAC_ADMIN))
Casey Schauflere114e472008-02-04 22:29:50 -08001820 return -EPERM;
1821
Al Viro16e5c1f2015-12-24 00:06:05 -05001822 data = memdup_user_nul(buf, count);
1823 if (IS_ERR(data))
1824 return PTR_ERR(data);
Casey Schauflere114e472008-02-04 22:29:50 -08001825
Casey Schaufler2f823ff2013-05-22 18:43:03 -07001826 skp = smk_import_entry(data, count);
Lukasz Pawelczyke774ad62015-04-20 17:12:54 +02001827 if (IS_ERR(skp)) {
1828 rc = PTR_ERR(skp);
Casey Schauflerf7112e62012-05-06 15:22:02 -07001829 goto out;
1830 }
Casey Schauflere114e472008-02-04 22:29:50 -08001831
Casey Schaufler4bc87e62008-02-15 15:24:25 -08001832 mutex_lock(&smack_ambient_lock);
1833
Casey Schaufler2f823ff2013-05-22 18:43:03 -07001834 oldambient = smack_net_ambient->smk_known;
1835 smack_net_ambient = skp;
Casey Schaufler4bc87e62008-02-15 15:24:25 -08001836 smk_unlbl_ambient(oldambient);
1837
1838 mutex_unlock(&smack_ambient_lock);
Casey Schauflere114e472008-02-04 22:29:50 -08001839
Casey Schauflerf7112e62012-05-06 15:22:02 -07001840out:
1841 kfree(data);
1842 return rc;
Casey Schauflere114e472008-02-04 22:29:50 -08001843}
1844
1845static const struct file_operations smk_ambient_ops = {
1846 .read = smk_read_ambient,
1847 .write = smk_write_ambient,
Arnd Bergmann6038f372010-08-15 18:52:59 +02001848 .llseek = default_llseek,
Casey Schauflere114e472008-02-04 22:29:50 -08001849};
1850
Rafal Krypac0d77c82015-06-02 11:23:48 +02001851/*
1852 * Seq_file operations for /smack/onlycap
Casey Schaufler15446232008-07-30 15:37:11 -07001853 */
Rafal Krypac0d77c82015-06-02 11:23:48 +02001854static void *onlycap_seq_start(struct seq_file *s, loff_t *pos)
Casey Schaufler15446232008-07-30 15:37:11 -07001855{
Rafal Krypac0d77c82015-06-02 11:23:48 +02001856 return smk_seq_start(s, pos, &smack_onlycap_list);
1857}
Casey Schaufler15446232008-07-30 15:37:11 -07001858
Rafal Krypac0d77c82015-06-02 11:23:48 +02001859static void *onlycap_seq_next(struct seq_file *s, void *v, loff_t *pos)
1860{
1861 return smk_seq_next(s, v, pos, &smack_onlycap_list);
1862}
Casey Schaufler15446232008-07-30 15:37:11 -07001863
Rafal Krypac0d77c82015-06-02 11:23:48 +02001864static int onlycap_seq_show(struct seq_file *s, void *v)
1865{
1866 struct list_head *list = v;
Zbigniew Jasinski38416e52015-10-19 18:23:53 +02001867 struct smack_known_list_elem *sklep =
1868 list_entry_rcu(list, struct smack_known_list_elem, list);
Casey Schaufler15446232008-07-30 15:37:11 -07001869
Zbigniew Jasinski38416e52015-10-19 18:23:53 +02001870 seq_puts(s, sklep->smk_label->smk_known);
Rafal Krypac0d77c82015-06-02 11:23:48 +02001871 seq_putc(s, ' ');
Casey Schaufler15446232008-07-30 15:37:11 -07001872
Rafal Krypac0d77c82015-06-02 11:23:48 +02001873 return 0;
1874}
Casey Schaufler15446232008-07-30 15:37:11 -07001875
Rafal Krypac0d77c82015-06-02 11:23:48 +02001876static const struct seq_operations onlycap_seq_ops = {
1877 .start = onlycap_seq_start,
1878 .next = onlycap_seq_next,
1879 .show = onlycap_seq_show,
1880 .stop = smk_seq_stop,
1881};
1882
1883static int smk_open_onlycap(struct inode *inode, struct file *file)
1884{
1885 return seq_open(file, &onlycap_seq_ops);
1886}
1887
1888/**
1889 * smk_list_swap_rcu - swap public list with a private one in RCU-safe way
1890 * The caller must hold appropriate mutex to prevent concurrent modifications
1891 * to the public list.
1892 * Private list is assumed to be not accessible to other threads yet.
1893 *
1894 * @public: public list
1895 * @private: private list
1896 */
1897static void smk_list_swap_rcu(struct list_head *public,
1898 struct list_head *private)
1899{
1900 struct list_head *first, *last;
1901
1902 if (list_empty(public)) {
1903 list_splice_init_rcu(private, public, synchronize_rcu);
1904 } else {
1905 /* Remember public list before replacing it */
1906 first = public->next;
1907 last = public->prev;
1908
1909 /* Publish private list in place of public in RCU-safe way */
1910 private->prev->next = public;
1911 private->next->prev = public;
1912 rcu_assign_pointer(public->next, private->next);
1913 public->prev = private->prev;
1914
1915 synchronize_rcu();
1916
1917 /* When all readers are done with the old public list,
1918 * attach it in place of private */
1919 private->next = first;
1920 private->prev = last;
1921 first->prev = private;
1922 last->next = private;
1923 }
Casey Schaufler15446232008-07-30 15:37:11 -07001924}
1925
1926/**
Zbigniew Jasinski38416e52015-10-19 18:23:53 +02001927 * smk_parse_label_list - parse list of Smack labels, separated by spaces
1928 *
1929 * @data: the string to parse
1930 * @private: destination list
1931 *
1932 * Returns zero on success or error code, as appropriate
1933 */
1934static int smk_parse_label_list(char *data, struct list_head *list)
1935{
1936 char *tok;
1937 struct smack_known *skp;
1938 struct smack_known_list_elem *sklep;
1939
1940 while ((tok = strsep(&data, " ")) != NULL) {
1941 if (!*tok)
1942 continue;
1943
1944 skp = smk_import_entry(tok, 0);
1945 if (IS_ERR(skp))
1946 return PTR_ERR(skp);
1947
1948 sklep = kzalloc(sizeof(*sklep), GFP_KERNEL);
1949 if (sklep == NULL)
1950 return -ENOMEM;
1951
1952 sklep->smk_label = skp;
1953 list_add(&sklep->list, list);
1954 }
1955
1956 return 0;
1957}
1958
1959/**
1960 * smk_destroy_label_list - destroy a list of smack_known_list_elem
1961 * @head: header pointer of the list to destroy
1962 */
1963void smk_destroy_label_list(struct list_head *list)
1964{
1965 struct smack_known_list_elem *sklep;
1966 struct smack_known_list_elem *sklep2;
1967
1968 list_for_each_entry_safe(sklep, sklep2, list, list)
1969 kfree(sklep);
1970
1971 INIT_LIST_HEAD(list);
1972}
1973
1974/**
Casey Schaufler00f84f32013-12-23 11:07:10 -08001975 * smk_write_onlycap - write() for smackfs/onlycap
Randy Dunlap251a2a92009-02-18 11:42:33 -08001976 * @file: file pointer, not actually used
Casey Schaufler15446232008-07-30 15:37:11 -07001977 * @buf: where to get the data from
1978 * @count: bytes sent
1979 * @ppos: where to start
1980 *
1981 * Returns number of bytes written or error code, as appropriate
1982 */
1983static ssize_t smk_write_onlycap(struct file *file, const char __user *buf,
1984 size_t count, loff_t *ppos)
1985{
Casey Schauflerf7112e62012-05-06 15:22:02 -07001986 char *data;
Rafal Krypac0d77c82015-06-02 11:23:48 +02001987 LIST_HEAD(list_tmp);
Zbigniew Jasinski38416e52015-10-19 18:23:53 +02001988 int rc;
Casey Schaufler15446232008-07-30 15:37:11 -07001989
Casey Schaufler1880eff2012-06-05 15:28:30 -07001990 if (!smack_privileged(CAP_MAC_ADMIN))
Casey Schaufler15446232008-07-30 15:37:11 -07001991 return -EPERM;
1992
Al Viro16e5c1f2015-12-24 00:06:05 -05001993 data = memdup_user_nul(buf, count);
1994 if (IS_ERR(data))
1995 return PTR_ERR(data);
Casey Schaufler15446232008-07-30 15:37:11 -07001996
Zbigniew Jasinski38416e52015-10-19 18:23:53 +02001997 rc = smk_parse_label_list(data, &list_tmp);
Rafal Krypac0d77c82015-06-02 11:23:48 +02001998 kfree(data);
1999
Lukasz Pawelczyke774ad62015-04-20 17:12:54 +02002000 /*
2001 * Clear the smack_onlycap on invalid label errors. This means
2002 * that we can pass a null string to unset the onlycap value.
2003 *
2004 * Importing will also reject a label beginning with '-',
2005 * so "-usecapabilities" will also work.
2006 *
2007 * But do so only on invalid label, not on system errors.
Rafal Krypac0d77c82015-06-02 11:23:48 +02002008 * The invalid label must be first to count as clearing attempt.
Lukasz Pawelczyke774ad62015-04-20 17:12:54 +02002009 */
Zbigniew Jasinski38416e52015-10-19 18:23:53 +02002010 if (!rc || (rc == -EINVAL && list_empty(&list_tmp))) {
Rafal Krypac0d77c82015-06-02 11:23:48 +02002011 mutex_lock(&smack_onlycap_lock);
2012 smk_list_swap_rcu(&smack_onlycap_list, &list_tmp);
2013 mutex_unlock(&smack_onlycap_lock);
Zbigniew Jasinski38416e52015-10-19 18:23:53 +02002014 rc = count;
Lukasz Pawelczyke774ad62015-04-20 17:12:54 +02002015 }
2016
Zbigniew Jasinski38416e52015-10-19 18:23:53 +02002017 smk_destroy_label_list(&list_tmp);
Lukasz Pawelczyke774ad62015-04-20 17:12:54 +02002018
Casey Schauflerf7112e62012-05-06 15:22:02 -07002019 return rc;
Casey Schaufler15446232008-07-30 15:37:11 -07002020}
2021
2022static const struct file_operations smk_onlycap_ops = {
Rafal Krypac0d77c82015-06-02 11:23:48 +02002023 .open = smk_open_onlycap,
2024 .read = seq_read,
Casey Schaufler15446232008-07-30 15:37:11 -07002025 .write = smk_write_onlycap,
Rafal Krypac0d77c82015-06-02 11:23:48 +02002026 .llseek = seq_lseek,
2027 .release = seq_release,
Casey Schaufler15446232008-07-30 15:37:11 -07002028};
2029
Casey Schauflerbf4b2fe2015-03-21 18:26:40 -07002030#ifdef CONFIG_SECURITY_SMACK_BRINGUP
2031/**
2032 * smk_read_unconfined - read() for smackfs/unconfined
2033 * @filp: file pointer, not actually used
2034 * @buf: where to put the result
2035 * @cn: maximum to send along
2036 * @ppos: where to start
2037 *
2038 * Returns number of bytes read or error code, as appropriate
2039 */
2040static ssize_t smk_read_unconfined(struct file *filp, char __user *buf,
2041 size_t cn, loff_t *ppos)
2042{
2043 char *smack = "";
2044 ssize_t rc = -EINVAL;
2045 int asize;
2046
2047 if (*ppos != 0)
2048 return 0;
2049
2050 if (smack_unconfined != NULL)
2051 smack = smack_unconfined->smk_known;
2052
2053 asize = strlen(smack) + 1;
2054
2055 if (cn >= asize)
2056 rc = simple_read_from_buffer(buf, cn, ppos, smack, asize);
2057
2058 return rc;
2059}
2060
2061/**
2062 * smk_write_unconfined - write() for smackfs/unconfined
2063 * @file: file pointer, not actually used
2064 * @buf: where to get the data from
2065 * @count: bytes sent
2066 * @ppos: where to start
2067 *
2068 * Returns number of bytes written or error code, as appropriate
2069 */
2070static ssize_t smk_write_unconfined(struct file *file, const char __user *buf,
2071 size_t count, loff_t *ppos)
2072{
2073 char *data;
Lukasz Pawelczyke774ad62015-04-20 17:12:54 +02002074 struct smack_known *skp;
Casey Schauflerbf4b2fe2015-03-21 18:26:40 -07002075 int rc = count;
2076
2077 if (!smack_privileged(CAP_MAC_ADMIN))
2078 return -EPERM;
2079
Al Viro16e5c1f2015-12-24 00:06:05 -05002080 data = memdup_user_nul(buf, count);
2081 if (IS_ERR(data))
2082 return PTR_ERR(data);
Casey Schauflerbf4b2fe2015-03-21 18:26:40 -07002083
Lukasz Pawelczyke774ad62015-04-20 17:12:54 +02002084 /*
2085 * Clear the smack_unconfined on invalid label errors. This means
2086 * that we can pass a null string to unset the unconfined value.
2087 *
2088 * Importing will also reject a label beginning with '-',
2089 * so "-confine" will also work.
2090 *
2091 * But do so only on invalid label, not on system errors.
2092 */
2093 skp = smk_import_entry(data, count);
2094 if (PTR_ERR(skp) == -EINVAL)
2095 skp = NULL;
2096 else if (IS_ERR(skp)) {
2097 rc = PTR_ERR(skp);
2098 goto freeout;
2099 }
2100
2101 smack_unconfined = skp;
2102
2103freeout:
Casey Schauflerbf4b2fe2015-03-21 18:26:40 -07002104 kfree(data);
2105 return rc;
2106}
2107
2108static const struct file_operations smk_unconfined_ops = {
2109 .read = smk_read_unconfined,
2110 .write = smk_write_unconfined,
2111 .llseek = default_llseek,
2112};
2113#endif /* CONFIG_SECURITY_SMACK_BRINGUP */
2114
Casey Schauflere114e472008-02-04 22:29:50 -08002115/**
Etienne Bassetecfcc532009-04-08 20:40:06 +02002116 * smk_read_logging - read() for /smack/logging
2117 * @filp: file pointer, not actually used
2118 * @buf: where to put the result
2119 * @cn: maximum to send along
2120 * @ppos: where to start
2121 *
2122 * Returns number of bytes read or error code, as appropriate
2123 */
2124static ssize_t smk_read_logging(struct file *filp, char __user *buf,
2125 size_t count, loff_t *ppos)
2126{
2127 char temp[32];
2128 ssize_t rc;
2129
2130 if (*ppos != 0)
2131 return 0;
2132
2133 sprintf(temp, "%d\n", log_policy);
2134 rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
2135 return rc;
2136}
2137
2138/**
2139 * smk_write_logging - write() for /smack/logging
2140 * @file: file pointer, not actually used
2141 * @buf: where to get the data from
2142 * @count: bytes sent
2143 * @ppos: where to start
2144 *
2145 * Returns number of bytes written or error code, as appropriate
2146 */
2147static ssize_t smk_write_logging(struct file *file, const char __user *buf,
2148 size_t count, loff_t *ppos)
2149{
2150 char temp[32];
2151 int i;
2152
Casey Schaufler1880eff2012-06-05 15:28:30 -07002153 if (!smack_privileged(CAP_MAC_ADMIN))
Etienne Bassetecfcc532009-04-08 20:40:06 +02002154 return -EPERM;
2155
2156 if (count >= sizeof(temp) || count == 0)
2157 return -EINVAL;
2158
2159 if (copy_from_user(temp, buf, count) != 0)
2160 return -EFAULT;
2161
2162 temp[count] = '\0';
2163
2164 if (sscanf(temp, "%d", &i) != 1)
2165 return -EINVAL;
2166 if (i < 0 || i > 3)
2167 return -EINVAL;
2168 log_policy = i;
2169 return count;
2170}
2171
2172
2173
2174static const struct file_operations smk_logging_ops = {
2175 .read = smk_read_logging,
2176 .write = smk_write_logging,
Arnd Bergmann6038f372010-08-15 18:52:59 +02002177 .llseek = default_llseek,
Etienne Bassetecfcc532009-04-08 20:40:06 +02002178};
Casey Schaufler7898e1f2011-01-17 08:05:27 -08002179
2180/*
2181 * Seq_file read operations for /smack/load-self
2182 */
2183
2184static void *load_self_seq_start(struct seq_file *s, loff_t *pos)
2185{
Casey Schauflerb17103a2018-11-09 16:12:56 -08002186 struct task_smack *tsp = smack_cred(current_cred());
Casey Schaufler7898e1f2011-01-17 08:05:27 -08002187
Casey Schaufler40809562011-11-10 15:02:22 -08002188 return smk_seq_start(s, pos, &tsp->smk_rules);
Casey Schaufler7898e1f2011-01-17 08:05:27 -08002189}
2190
2191static void *load_self_seq_next(struct seq_file *s, void *v, loff_t *pos)
2192{
Casey Schauflerb17103a2018-11-09 16:12:56 -08002193 struct task_smack *tsp = smack_cred(current_cred());
Casey Schaufler7898e1f2011-01-17 08:05:27 -08002194
Casey Schaufler40809562011-11-10 15:02:22 -08002195 return smk_seq_next(s, v, pos, &tsp->smk_rules);
Casey Schaufler7898e1f2011-01-17 08:05:27 -08002196}
2197
2198static int load_self_seq_show(struct seq_file *s, void *v)
2199{
2200 struct list_head *list = v;
2201 struct smack_rule *srp =
Rafal Krypa01fa8472015-05-21 18:24:31 +02002202 list_entry_rcu(list, struct smack_rule, list);
Casey Schaufler7898e1f2011-01-17 08:05:27 -08002203
Casey Schauflerf7112e62012-05-06 15:22:02 -07002204 smk_rule_show(s, srp, SMK_LABELLEN);
Casey Schaufler7898e1f2011-01-17 08:05:27 -08002205
2206 return 0;
2207}
2208
Casey Schaufler7898e1f2011-01-17 08:05:27 -08002209static const struct seq_operations load_self_seq_ops = {
2210 .start = load_self_seq_start,
2211 .next = load_self_seq_next,
2212 .show = load_self_seq_show,
Casey Schaufler40809562011-11-10 15:02:22 -08002213 .stop = smk_seq_stop,
Casey Schaufler7898e1f2011-01-17 08:05:27 -08002214};
2215
2216
2217/**
Casey Schauflerf7112e62012-05-06 15:22:02 -07002218 * smk_open_load_self - open() for /smack/load-self2
Casey Schaufler7898e1f2011-01-17 08:05:27 -08002219 * @inode: inode structure representing file
2220 * @file: "load" file pointer
2221 *
2222 * For reading, use load_seq_* seq_file reading operations.
2223 */
2224static int smk_open_load_self(struct inode *inode, struct file *file)
2225{
2226 return seq_open(file, &load_self_seq_ops);
2227}
2228
2229/**
2230 * smk_write_load_self - write() for /smack/load-self
2231 * @file: file pointer, not actually used
2232 * @buf: where to get the data from
2233 * @count: bytes sent
2234 * @ppos: where to start - must be 0
2235 *
2236 */
2237static ssize_t smk_write_load_self(struct file *file, const char __user *buf,
2238 size_t count, loff_t *ppos)
2239{
Casey Schauflerb17103a2018-11-09 16:12:56 -08002240 struct task_smack *tsp = smack_cred(current_cred());
Casey Schaufler7898e1f2011-01-17 08:05:27 -08002241
Casey Schauflerf7112e62012-05-06 15:22:02 -07002242 return smk_write_rules_list(file, buf, count, ppos, &tsp->smk_rules,
2243 &tsp->smk_rules_lock, SMK_FIXED24_FMT);
Casey Schaufler7898e1f2011-01-17 08:05:27 -08002244}
2245
2246static const struct file_operations smk_load_self_ops = {
2247 .open = smk_open_load_self,
2248 .read = seq_read,
2249 .llseek = seq_lseek,
2250 .write = smk_write_load_self,
2251 .release = seq_release,
2252};
Jarkko Sakkinen828716c2011-09-08 10:12:01 +03002253
2254/**
Casey Schauflerf7112e62012-05-06 15:22:02 -07002255 * smk_user_access - handle access check transaction
2256 * @file: file pointer
2257 * @buf: data from user space
2258 * @count: bytes sent
2259 * @ppos: where to start - must be 0
2260 */
2261static ssize_t smk_user_access(struct file *file, const char __user *buf,
2262 size_t count, loff_t *ppos, int format)
2263{
Rafal Krypae05b6f92013-01-10 19:42:00 +01002264 struct smack_parsed_rule rule;
Casey Schauflerf7112e62012-05-06 15:22:02 -07002265 char *data;
Casey Schauflerf7112e62012-05-06 15:22:02 -07002266 int res;
2267
2268 data = simple_transaction_get(file, buf, count);
2269 if (IS_ERR(data))
2270 return PTR_ERR(data);
2271
2272 if (format == SMK_FIXED24_FMT) {
2273 if (count < SMK_LOADLEN)
2274 return -EINVAL;
2275 res = smk_parse_rule(data, &rule, 0);
2276 } else {
2277 /*
Rafal Krypa10289b02013-08-09 11:47:07 +02002278 * simple_transaction_get() returns null-terminated data
Casey Schauflerf7112e62012-05-06 15:22:02 -07002279 */
Rafal Krypa10289b02013-08-09 11:47:07 +02002280 res = smk_parse_long_rule(data, &rule, 0, 3);
Casey Schauflerf7112e62012-05-06 15:22:02 -07002281 }
2282
Jarkko Sakkinen398ce072013-11-28 19:16:46 +02002283 if (res >= 0)
2284 res = smk_access(rule.smk_subject, rule.smk_object,
2285 rule.smk_access1, NULL);
2286 else if (res != -ENOENT)
Lukasz Pawelczyke774ad62015-04-20 17:12:54 +02002287 return res;
Casey Schauflerf7112e62012-05-06 15:22:02 -07002288
Casey Schauflerd166c802014-08-27 14:51:27 -07002289 /*
2290 * smk_access() can return a value > 0 in the "bringup" case.
2291 */
2292 data[0] = res >= 0 ? '1' : '0';
Casey Schauflerf7112e62012-05-06 15:22:02 -07002293 data[1] = '\0';
2294
2295 simple_transaction_set(file, 2);
2296
2297 if (format == SMK_FIXED24_FMT)
2298 return SMK_LOADLEN;
2299 return count;
2300}
2301
2302/**
Jarkko Sakkinen828716c2011-09-08 10:12:01 +03002303 * smk_write_access - handle access check transaction
2304 * @file: file pointer
2305 * @buf: data from user space
2306 * @count: bytes sent
2307 * @ppos: where to start - must be 0
2308 */
2309static ssize_t smk_write_access(struct file *file, const char __user *buf,
2310 size_t count, loff_t *ppos)
2311{
Casey Schauflerf7112e62012-05-06 15:22:02 -07002312 return smk_user_access(file, buf, count, ppos, SMK_FIXED24_FMT);
Jarkko Sakkinen828716c2011-09-08 10:12:01 +03002313}
2314
2315static const struct file_operations smk_access_ops = {
2316 .write = smk_write_access,
2317 .read = simple_transaction_read,
2318 .release = simple_transaction_release,
2319 .llseek = generic_file_llseek,
2320};
2321
Casey Schauflerf7112e62012-05-06 15:22:02 -07002322
2323/*
2324 * Seq_file read operations for /smack/load2
2325 */
2326
2327static int load2_seq_show(struct seq_file *s, void *v)
2328{
2329 struct list_head *list = v;
Vishal Goel460d95a2019-03-07 16:55:24 +05302330 struct smack_rule *srp;
2331 struct smack_known *skp =
2332 list_entry_rcu(list, struct smack_known, list);
Casey Schauflerf7112e62012-05-06 15:22:02 -07002333
Vishal Goel460d95a2019-03-07 16:55:24 +05302334 list_for_each_entry_rcu(srp, &skp->smk_rules, list)
2335 smk_rule_show(s, srp, SMK_LONGLABEL);
Casey Schauflerf7112e62012-05-06 15:22:02 -07002336
2337 return 0;
2338}
2339
2340static const struct seq_operations load2_seq_ops = {
2341 .start = load2_seq_start,
2342 .next = load2_seq_next,
2343 .show = load2_seq_show,
2344 .stop = smk_seq_stop,
2345};
2346
2347/**
2348 * smk_open_load2 - open() for /smack/load2
2349 * @inode: inode structure representing file
2350 * @file: "load2" file pointer
2351 *
2352 * For reading, use load2_seq_* seq_file reading operations.
2353 */
2354static int smk_open_load2(struct inode *inode, struct file *file)
2355{
2356 return seq_open(file, &load2_seq_ops);
2357}
2358
2359/**
2360 * smk_write_load2 - write() for /smack/load2
2361 * @file: file pointer, not actually used
2362 * @buf: where to get the data from
2363 * @count: bytes sent
2364 * @ppos: where to start - must be 0
2365 *
2366 */
2367static ssize_t smk_write_load2(struct file *file, const char __user *buf,
2368 size_t count, loff_t *ppos)
2369{
2370 /*
2371 * Must have privilege.
2372 */
Casey Schaufler1880eff2012-06-05 15:28:30 -07002373 if (!smack_privileged(CAP_MAC_ADMIN))
Casey Schauflerf7112e62012-05-06 15:22:02 -07002374 return -EPERM;
2375
2376 return smk_write_rules_list(file, buf, count, ppos, NULL, NULL,
2377 SMK_LONG_FMT);
2378}
2379
2380static const struct file_operations smk_load2_ops = {
2381 .open = smk_open_load2,
2382 .read = seq_read,
2383 .llseek = seq_lseek,
2384 .write = smk_write_load2,
2385 .release = seq_release,
2386};
2387
2388/*
2389 * Seq_file read operations for /smack/load-self2
2390 */
2391
2392static void *load_self2_seq_start(struct seq_file *s, loff_t *pos)
2393{
Casey Schauflerb17103a2018-11-09 16:12:56 -08002394 struct task_smack *tsp = smack_cred(current_cred());
Casey Schauflerf7112e62012-05-06 15:22:02 -07002395
2396 return smk_seq_start(s, pos, &tsp->smk_rules);
2397}
2398
2399static void *load_self2_seq_next(struct seq_file *s, void *v, loff_t *pos)
2400{
Casey Schauflerb17103a2018-11-09 16:12:56 -08002401 struct task_smack *tsp = smack_cred(current_cred());
Casey Schauflerf7112e62012-05-06 15:22:02 -07002402
2403 return smk_seq_next(s, v, pos, &tsp->smk_rules);
2404}
2405
2406static int load_self2_seq_show(struct seq_file *s, void *v)
2407{
2408 struct list_head *list = v;
2409 struct smack_rule *srp =
Rafal Krypa01fa8472015-05-21 18:24:31 +02002410 list_entry_rcu(list, struct smack_rule, list);
Casey Schauflerf7112e62012-05-06 15:22:02 -07002411
2412 smk_rule_show(s, srp, SMK_LONGLABEL);
2413
2414 return 0;
2415}
2416
2417static const struct seq_operations load_self2_seq_ops = {
2418 .start = load_self2_seq_start,
2419 .next = load_self2_seq_next,
2420 .show = load_self2_seq_show,
2421 .stop = smk_seq_stop,
2422};
2423
2424/**
2425 * smk_open_load_self2 - open() for /smack/load-self2
2426 * @inode: inode structure representing file
2427 * @file: "load" file pointer
2428 *
2429 * For reading, use load_seq_* seq_file reading operations.
2430 */
2431static int smk_open_load_self2(struct inode *inode, struct file *file)
2432{
2433 return seq_open(file, &load_self2_seq_ops);
2434}
2435
2436/**
2437 * smk_write_load_self2 - write() for /smack/load-self2
2438 * @file: file pointer, not actually used
2439 * @buf: where to get the data from
2440 * @count: bytes sent
2441 * @ppos: where to start - must be 0
2442 *
2443 */
2444static ssize_t smk_write_load_self2(struct file *file, const char __user *buf,
2445 size_t count, loff_t *ppos)
2446{
Casey Schauflerb17103a2018-11-09 16:12:56 -08002447 struct task_smack *tsp = smack_cred(current_cred());
Casey Schauflerf7112e62012-05-06 15:22:02 -07002448
2449 return smk_write_rules_list(file, buf, count, ppos, &tsp->smk_rules,
2450 &tsp->smk_rules_lock, SMK_LONG_FMT);
2451}
2452
2453static const struct file_operations smk_load_self2_ops = {
2454 .open = smk_open_load_self2,
2455 .read = seq_read,
2456 .llseek = seq_lseek,
2457 .write = smk_write_load_self2,
2458 .release = seq_release,
2459};
2460
2461/**
2462 * smk_write_access2 - handle access check transaction
2463 * @file: file pointer
2464 * @buf: data from user space
2465 * @count: bytes sent
2466 * @ppos: where to start - must be 0
2467 */
2468static ssize_t smk_write_access2(struct file *file, const char __user *buf,
2469 size_t count, loff_t *ppos)
2470{
2471 return smk_user_access(file, buf, count, ppos, SMK_LONG_FMT);
2472}
2473
2474static const struct file_operations smk_access2_ops = {
2475 .write = smk_write_access2,
2476 .read = simple_transaction_read,
2477 .release = simple_transaction_release,
2478 .llseek = generic_file_llseek,
2479};
2480
Etienne Bassetecfcc532009-04-08 20:40:06 +02002481/**
Rafal Krypa449543b2012-07-11 17:49:30 +02002482 * smk_write_revoke_subj - write() for /smack/revoke-subject
2483 * @file: file pointer
2484 * @buf: data from user space
2485 * @count: bytes sent
2486 * @ppos: where to start - must be 0
2487 */
2488static ssize_t smk_write_revoke_subj(struct file *file, const char __user *buf,
2489 size_t count, loff_t *ppos)
2490{
Dan Carpenter54302092015-06-11 11:51:16 +03002491 char *data;
2492 const char *cp;
Rafal Krypa449543b2012-07-11 17:49:30 +02002493 struct smack_known *skp;
2494 struct smack_rule *sp;
2495 struct list_head *rule_list;
2496 struct mutex *rule_lock;
2497 int rc = count;
2498
2499 if (*ppos != 0)
2500 return -EINVAL;
2501
2502 if (!smack_privileged(CAP_MAC_ADMIN))
2503 return -EPERM;
2504
2505 if (count == 0 || count > SMK_LONGLABEL)
2506 return -EINVAL;
2507
Markus Elfring63e24c42016-08-21 20:17:36 +02002508 data = memdup_user(buf, count);
2509 if (IS_ERR(data))
2510 return PTR_ERR(data);
Rafal Krypa449543b2012-07-11 17:49:30 +02002511
2512 cp = smk_parse_smack(data, count);
Lukasz Pawelczyke774ad62015-04-20 17:12:54 +02002513 if (IS_ERR(cp)) {
2514 rc = PTR_ERR(cp);
Dan Carpenter54302092015-06-11 11:51:16 +03002515 goto out_data;
Rafal Krypa449543b2012-07-11 17:49:30 +02002516 }
2517
2518 skp = smk_find_entry(cp);
Rafal Krypad15d9fa2012-11-27 16:28:11 +01002519 if (skp == NULL)
Dan Carpenter54302092015-06-11 11:51:16 +03002520 goto out_cp;
Rafal Krypa449543b2012-07-11 17:49:30 +02002521
2522 rule_list = &skp->smk_rules;
2523 rule_lock = &skp->smk_rules_lock;
2524
2525 mutex_lock(rule_lock);
2526
2527 list_for_each_entry_rcu(sp, rule_list, list)
2528 sp->smk_access = 0;
2529
2530 mutex_unlock(rule_lock);
2531
Dan Carpenter54302092015-06-11 11:51:16 +03002532out_cp:
Rafal Krypa449543b2012-07-11 17:49:30 +02002533 kfree(cp);
Dan Carpenter54302092015-06-11 11:51:16 +03002534out_data:
2535 kfree(data);
2536
Rafal Krypa449543b2012-07-11 17:49:30 +02002537 return rc;
2538}
2539
2540static const struct file_operations smk_revoke_subj_ops = {
2541 .write = smk_write_revoke_subj,
2542 .read = simple_transaction_read,
2543 .release = simple_transaction_release,
2544 .llseek = generic_file_llseek,
2545};
2546
Casey Schauflere93072372012-11-01 18:14:32 -07002547/**
2548 * smk_init_sysfs - initialize /sys/fs/smackfs
2549 *
2550 */
2551static int smk_init_sysfs(void)
2552{
kbuild test robotca70d272015-06-24 07:41:07 +08002553 return sysfs_create_mount_point(fs_kobj, "smackfs");
Casey Schauflere93072372012-11-01 18:14:32 -07002554}
2555
Rafal Krypa449543b2012-07-11 17:49:30 +02002556/**
Rafal Krypae05b6f92013-01-10 19:42:00 +01002557 * smk_write_change_rule - write() for /smack/change-rule
2558 * @file: file pointer
2559 * @buf: data from user space
2560 * @count: bytes sent
2561 * @ppos: where to start - must be 0
2562 */
2563static ssize_t smk_write_change_rule(struct file *file, const char __user *buf,
2564 size_t count, loff_t *ppos)
2565{
2566 /*
2567 * Must have privilege.
2568 */
Casey Schaufler4afde482013-12-19 13:23:26 -08002569 if (!smack_privileged(CAP_MAC_ADMIN))
Rafal Krypae05b6f92013-01-10 19:42:00 +01002570 return -EPERM;
2571
2572 return smk_write_rules_list(file, buf, count, ppos, NULL, NULL,
2573 SMK_CHANGE_FMT);
2574}
2575
2576static const struct file_operations smk_change_rule_ops = {
2577 .write = smk_write_change_rule,
2578 .read = simple_transaction_read,
2579 .release = simple_transaction_release,
2580 .llseek = generic_file_llseek,
2581};
2582
2583/**
Casey Schaufler00f84f32013-12-23 11:07:10 -08002584 * smk_read_syslog - read() for smackfs/syslog
2585 * @filp: file pointer, not actually used
2586 * @buf: where to put the result
2587 * @cn: maximum to send along
2588 * @ppos: where to start
2589 *
2590 * Returns number of bytes read or error code, as appropriate
2591 */
2592static ssize_t smk_read_syslog(struct file *filp, char __user *buf,
2593 size_t cn, loff_t *ppos)
2594{
2595 struct smack_known *skp;
2596 ssize_t rc = -EINVAL;
2597 int asize;
2598
2599 if (*ppos != 0)
2600 return 0;
2601
2602 if (smack_syslog_label == NULL)
2603 skp = &smack_known_star;
2604 else
2605 skp = smack_syslog_label;
2606
2607 asize = strlen(skp->smk_known) + 1;
2608
2609 if (cn >= asize)
2610 rc = simple_read_from_buffer(buf, cn, ppos, skp->smk_known,
2611 asize);
2612
2613 return rc;
2614}
2615
2616/**
2617 * smk_write_syslog - write() for smackfs/syslog
2618 * @file: file pointer, not actually used
2619 * @buf: where to get the data from
2620 * @count: bytes sent
2621 * @ppos: where to start
2622 *
2623 * Returns number of bytes written or error code, as appropriate
2624 */
2625static ssize_t smk_write_syslog(struct file *file, const char __user *buf,
2626 size_t count, loff_t *ppos)
2627{
2628 char *data;
2629 struct smack_known *skp;
2630 int rc = count;
2631
2632 if (!smack_privileged(CAP_MAC_ADMIN))
2633 return -EPERM;
2634
Al Viro16e5c1f2015-12-24 00:06:05 -05002635 data = memdup_user_nul(buf, count);
2636 if (IS_ERR(data))
2637 return PTR_ERR(data);
Casey Schaufler00f84f32013-12-23 11:07:10 -08002638
Al Viro16e5c1f2015-12-24 00:06:05 -05002639 skp = smk_import_entry(data, count);
2640 if (IS_ERR(skp))
2641 rc = PTR_ERR(skp);
2642 else
2643 smack_syslog_label = skp;
Casey Schaufler00f84f32013-12-23 11:07:10 -08002644
2645 kfree(data);
2646 return rc;
2647}
2648
2649static const struct file_operations smk_syslog_ops = {
2650 .read = smk_read_syslog,
2651 .write = smk_write_syslog,
2652 .llseek = default_llseek,
2653};
2654
Zbigniew Jasinski38416e52015-10-19 18:23:53 +02002655/*
2656 * Seq_file read operations for /smack/relabel-self
2657 */
2658
2659static void *relabel_self_seq_start(struct seq_file *s, loff_t *pos)
2660{
Casey Schauflerb17103a2018-11-09 16:12:56 -08002661 struct task_smack *tsp = smack_cred(current_cred());
Zbigniew Jasinski38416e52015-10-19 18:23:53 +02002662
2663 return smk_seq_start(s, pos, &tsp->smk_relabel);
2664}
2665
2666static void *relabel_self_seq_next(struct seq_file *s, void *v, loff_t *pos)
2667{
Casey Schauflerb17103a2018-11-09 16:12:56 -08002668 struct task_smack *tsp = smack_cred(current_cred());
Zbigniew Jasinski38416e52015-10-19 18:23:53 +02002669
2670 return smk_seq_next(s, v, pos, &tsp->smk_relabel);
2671}
2672
2673static int relabel_self_seq_show(struct seq_file *s, void *v)
2674{
2675 struct list_head *list = v;
2676 struct smack_known_list_elem *sklep =
2677 list_entry(list, struct smack_known_list_elem, list);
2678
2679 seq_puts(s, sklep->smk_label->smk_known);
2680 seq_putc(s, ' ');
2681
2682 return 0;
2683}
2684
2685static const struct seq_operations relabel_self_seq_ops = {
2686 .start = relabel_self_seq_start,
2687 .next = relabel_self_seq_next,
2688 .show = relabel_self_seq_show,
2689 .stop = smk_seq_stop,
2690};
2691
2692/**
2693 * smk_open_relabel_self - open() for /smack/relabel-self
2694 * @inode: inode structure representing file
2695 * @file: "relabel-self" file pointer
2696 *
2697 * Connect our relabel_self_seq_* operations with /smack/relabel-self
2698 * file_operations
2699 */
2700static int smk_open_relabel_self(struct inode *inode, struct file *file)
2701{
2702 return seq_open(file, &relabel_self_seq_ops);
2703}
2704
2705/**
2706 * smk_write_relabel_self - write() for /smack/relabel-self
2707 * @file: file pointer, not actually used
2708 * @buf: where to get the data from
2709 * @count: bytes sent
2710 * @ppos: where to start - must be 0
2711 *
2712 */
2713static ssize_t smk_write_relabel_self(struct file *file, const char __user *buf,
2714 size_t count, loff_t *ppos)
2715{
Casey Schauflerb17103a2018-11-09 16:12:56 -08002716 struct task_smack *tsp = smack_cred(current_cred());
Zbigniew Jasinski38416e52015-10-19 18:23:53 +02002717 char *data;
2718 int rc;
2719 LIST_HEAD(list_tmp);
2720
2721 /*
2722 * Must have privilege.
2723 */
2724 if (!smack_privileged(CAP_MAC_ADMIN))
2725 return -EPERM;
2726
2727 /*
2728 * Enough data must be present.
2729 */
2730 if (*ppos != 0)
2731 return -EINVAL;
2732
Al Viro16e5c1f2015-12-24 00:06:05 -05002733 data = memdup_user_nul(buf, count);
2734 if (IS_ERR(data))
2735 return PTR_ERR(data);
Zbigniew Jasinski38416e52015-10-19 18:23:53 +02002736
2737 rc = smk_parse_label_list(data, &list_tmp);
2738 kfree(data);
2739
2740 if (!rc || (rc == -EINVAL && list_empty(&list_tmp))) {
2741 smk_destroy_label_list(&tsp->smk_relabel);
2742 list_splice(&list_tmp, &tsp->smk_relabel);
2743 return count;
2744 }
2745
2746 smk_destroy_label_list(&list_tmp);
2747 return rc;
2748}
2749
2750static const struct file_operations smk_relabel_self_ops = {
2751 .open = smk_open_relabel_self,
2752 .read = seq_read,
2753 .llseek = seq_lseek,
2754 .write = smk_write_relabel_self,
2755 .release = seq_release,
2756};
Casey Schaufler00f84f32013-12-23 11:07:10 -08002757
2758/**
Lukasz Pawelczyk66867812014-03-11 17:07:06 +01002759 * smk_read_ptrace - read() for /smack/ptrace
2760 * @filp: file pointer, not actually used
2761 * @buf: where to put the result
2762 * @count: maximum to send along
2763 * @ppos: where to start
2764 *
2765 * Returns number of bytes read or error code, as appropriate
2766 */
2767static ssize_t smk_read_ptrace(struct file *filp, char __user *buf,
2768 size_t count, loff_t *ppos)
2769{
2770 char temp[32];
2771 ssize_t rc;
2772
2773 if (*ppos != 0)
2774 return 0;
2775
2776 sprintf(temp, "%d\n", smack_ptrace_rule);
2777 rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
2778 return rc;
2779}
2780
2781/**
2782 * smk_write_ptrace - write() for /smack/ptrace
2783 * @file: file pointer
2784 * @buf: data from user space
2785 * @count: bytes sent
2786 * @ppos: where to start - must be 0
2787 */
2788static ssize_t smk_write_ptrace(struct file *file, const char __user *buf,
2789 size_t count, loff_t *ppos)
2790{
2791 char temp[32];
2792 int i;
2793
2794 if (!smack_privileged(CAP_MAC_ADMIN))
2795 return -EPERM;
2796
2797 if (*ppos != 0 || count >= sizeof(temp) || count == 0)
2798 return -EINVAL;
2799
2800 if (copy_from_user(temp, buf, count) != 0)
2801 return -EFAULT;
2802
2803 temp[count] = '\0';
2804
2805 if (sscanf(temp, "%d", &i) != 1)
2806 return -EINVAL;
2807 if (i < SMACK_PTRACE_DEFAULT || i > SMACK_PTRACE_MAX)
2808 return -EINVAL;
2809 smack_ptrace_rule = i;
2810
2811 return count;
2812}
2813
2814static const struct file_operations smk_ptrace_ops = {
2815 .write = smk_write_ptrace,
2816 .read = smk_read_ptrace,
2817 .llseek = default_llseek,
2818};
2819
2820/**
Casey Schaufler00f84f32013-12-23 11:07:10 -08002821 * smk_fill_super - fill the smackfs superblock
Casey Schauflere114e472008-02-04 22:29:50 -08002822 * @sb: the empty superblock
2823 * @data: unused
2824 * @silent: unused
2825 *
Casey Schaufler00f84f32013-12-23 11:07:10 -08002826 * Fill in the well known entries for the smack filesystem
Casey Schauflere114e472008-02-04 22:29:50 -08002827 *
2828 * Returns 0 on success, an error code on failure
2829 */
2830static int smk_fill_super(struct super_block *sb, void *data, int silent)
2831{
2832 int rc;
Casey Schauflere114e472008-02-04 22:29:50 -08002833
Eric Biggerscda37122017-03-25 21:15:37 -07002834 static const struct tree_descr smack_files[] = {
Casey Schaufler7898e1f2011-01-17 08:05:27 -08002835 [SMK_LOAD] = {
2836 "load", &smk_load_ops, S_IRUGO|S_IWUSR},
2837 [SMK_CIPSO] = {
2838 "cipso", &smk_cipso_ops, S_IRUGO|S_IWUSR},
2839 [SMK_DOI] = {
2840 "doi", &smk_doi_ops, S_IRUGO|S_IWUSR},
2841 [SMK_DIRECT] = {
2842 "direct", &smk_direct_ops, S_IRUGO|S_IWUSR},
2843 [SMK_AMBIENT] = {
2844 "ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR},
Casey Schaufler21abb1e2015-07-22 14:25:31 -07002845 [SMK_NET4ADDR] = {
2846 "netlabel", &smk_net4addr_ops, S_IRUGO|S_IWUSR},
Casey Schaufler7898e1f2011-01-17 08:05:27 -08002847 [SMK_ONLYCAP] = {
2848 "onlycap", &smk_onlycap_ops, S_IRUGO|S_IWUSR},
2849 [SMK_LOGGING] = {
2850 "logging", &smk_logging_ops, S_IRUGO|S_IWUSR},
2851 [SMK_LOAD_SELF] = {
2852 "load-self", &smk_load_self_ops, S_IRUGO|S_IWUGO},
Jarkko Sakkinen828716c2011-09-08 10:12:01 +03002853 [SMK_ACCESSES] = {
Jarkko Sakkinen0e94ae12011-10-18 21:21:36 +03002854 "access", &smk_access_ops, S_IRUGO|S_IWUGO},
Casey Schauflerf7112e62012-05-06 15:22:02 -07002855 [SMK_MAPPED] = {
2856 "mapped", &smk_mapped_ops, S_IRUGO|S_IWUSR},
2857 [SMK_LOAD2] = {
2858 "load2", &smk_load2_ops, S_IRUGO|S_IWUSR},
2859 [SMK_LOAD_SELF2] = {
2860 "load-self2", &smk_load_self2_ops, S_IRUGO|S_IWUGO},
2861 [SMK_ACCESS2] = {
2862 "access2", &smk_access2_ops, S_IRUGO|S_IWUGO},
2863 [SMK_CIPSO2] = {
2864 "cipso2", &smk_cipso2_ops, S_IRUGO|S_IWUSR},
Rafal Krypa449543b2012-07-11 17:49:30 +02002865 [SMK_REVOKE_SUBJ] = {
2866 "revoke-subject", &smk_revoke_subj_ops,
2867 S_IRUGO|S_IWUSR},
Rafal Krypae05b6f92013-01-10 19:42:00 +01002868 [SMK_CHANGE_RULE] = {
2869 "change-rule", &smk_change_rule_ops, S_IRUGO|S_IWUSR},
Casey Schaufler00f84f32013-12-23 11:07:10 -08002870 [SMK_SYSLOG] = {
2871 "syslog", &smk_syslog_ops, S_IRUGO|S_IWUSR},
Lukasz Pawelczyk66867812014-03-11 17:07:06 +01002872 [SMK_PTRACE] = {
2873 "ptrace", &smk_ptrace_ops, S_IRUGO|S_IWUSR},
Casey Schauflerbf4b2fe2015-03-21 18:26:40 -07002874#ifdef CONFIG_SECURITY_SMACK_BRINGUP
2875 [SMK_UNCONFINED] = {
2876 "unconfined", &smk_unconfined_ops, S_IRUGO|S_IWUSR},
2877#endif
Casey Schaufler21abb1e2015-07-22 14:25:31 -07002878#if IS_ENABLED(CONFIG_IPV6)
2879 [SMK_NET6ADDR] = {
2880 "ipv6host", &smk_net6addr_ops, S_IRUGO|S_IWUSR},
2881#endif /* CONFIG_IPV6 */
Zbigniew Jasinski38416e52015-10-19 18:23:53 +02002882 [SMK_RELABEL_SELF] = {
2883 "relabel-self", &smk_relabel_self_ops,
2884 S_IRUGO|S_IWUGO},
Casey Schaufler7898e1f2011-01-17 08:05:27 -08002885 /* last one */
2886 {""}
Casey Schauflere114e472008-02-04 22:29:50 -08002887 };
2888
2889 rc = simple_fill_super(sb, SMACK_MAGIC, smack_files);
2890 if (rc != 0) {
2891 printk(KERN_ERR "%s failed %d while creating inodes\n",
2892 __func__, rc);
2893 return rc;
2894 }
2895
Casey Schauflere114e472008-02-04 22:29:50 -08002896 return 0;
2897}
2898
2899/**
Al Virofc14f2f2010-07-25 01:48:30 +04002900 * smk_mount - get the smackfs superblock
Casey Schauflere114e472008-02-04 22:29:50 -08002901 * @fs_type: passed along without comment
2902 * @flags: passed along without comment
2903 * @dev_name: passed along without comment
2904 * @data: passed along without comment
Casey Schauflere114e472008-02-04 22:29:50 -08002905 *
2906 * Just passes everything along.
2907 *
2908 * Returns what the lower level code does.
2909 */
Al Virofc14f2f2010-07-25 01:48:30 +04002910static struct dentry *smk_mount(struct file_system_type *fs_type,
2911 int flags, const char *dev_name, void *data)
Casey Schauflere114e472008-02-04 22:29:50 -08002912{
Al Virofc14f2f2010-07-25 01:48:30 +04002913 return mount_single(fs_type, flags, data, smk_fill_super);
Casey Schauflere114e472008-02-04 22:29:50 -08002914}
2915
2916static struct file_system_type smk_fs_type = {
2917 .name = "smackfs",
Al Virofc14f2f2010-07-25 01:48:30 +04002918 .mount = smk_mount,
Casey Schauflere114e472008-02-04 22:29:50 -08002919 .kill_sb = kill_litter_super,
2920};
2921
2922static struct vfsmount *smackfs_mount;
2923
Casey Schauflerf7112e62012-05-06 15:22:02 -07002924static int __init smk_preset_netlabel(struct smack_known *skp)
2925{
2926 skp->smk_netlabel.domain = skp->smk_known;
2927 skp->smk_netlabel.flags =
2928 NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL;
2929 return smk_netlbl_mls(smack_cipso_direct, skp->smk_known,
2930 &skp->smk_netlabel, strlen(skp->smk_known));
2931}
2932
Casey Schauflere114e472008-02-04 22:29:50 -08002933/**
2934 * init_smk_fs - get the smackfs superblock
2935 *
2936 * register the smackfs
2937 *
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02002938 * Do not register smackfs if Smack wasn't enabled
2939 * on boot. We can not put this method normally under the
2940 * smack_init() code path since the security subsystem get
2941 * initialized before the vfs caches.
2942 *
2943 * Returns true if we were not chosen on boot or if
2944 * we were chosen and filesystem registration succeeded.
Casey Schauflere114e472008-02-04 22:29:50 -08002945 */
2946static int __init init_smk_fs(void)
2947{
2948 int err;
Casey Schauflerf7112e62012-05-06 15:22:02 -07002949 int rc;
Casey Schauflere114e472008-02-04 22:29:50 -08002950
José Bollod21b7b02015-10-02 15:15:56 +02002951 if (smack_enabled == 0)
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02002952 return 0;
2953
Casey Schauflere93072372012-11-01 18:14:32 -07002954 err = smk_init_sysfs();
2955 if (err)
2956 printk(KERN_ERR "smackfs: sysfs mountpoint problem.\n");
2957
Casey Schauflere114e472008-02-04 22:29:50 -08002958 err = register_filesystem(&smk_fs_type);
2959 if (!err) {
2960 smackfs_mount = kern_mount(&smk_fs_type);
2961 if (IS_ERR(smackfs_mount)) {
2962 printk(KERN_ERR "smackfs: could not mount!\n");
2963 err = PTR_ERR(smackfs_mount);
2964 smackfs_mount = NULL;
2965 }
2966 }
2967
Casey Schauflere114e472008-02-04 22:29:50 -08002968 smk_cipso_doi();
Casey Schaufler4bc87e62008-02-15 15:24:25 -08002969 smk_unlbl_ambient(NULL);
Casey Schauflere114e472008-02-04 22:29:50 -08002970
Casey Schauflerf7112e62012-05-06 15:22:02 -07002971 rc = smk_preset_netlabel(&smack_known_floor);
2972 if (err == 0 && rc < 0)
2973 err = rc;
2974 rc = smk_preset_netlabel(&smack_known_hat);
2975 if (err == 0 && rc < 0)
2976 err = rc;
2977 rc = smk_preset_netlabel(&smack_known_huh);
2978 if (err == 0 && rc < 0)
2979 err = rc;
Casey Schauflerf7112e62012-05-06 15:22:02 -07002980 rc = smk_preset_netlabel(&smack_known_star);
2981 if (err == 0 && rc < 0)
2982 err = rc;
2983 rc = smk_preset_netlabel(&smack_known_web);
2984 if (err == 0 && rc < 0)
2985 err = rc;
2986
Casey Schauflere114e472008-02-04 22:29:50 -08002987 return err;
2988}
2989
2990__initcall(init_smk_fs);