Blame view

security/smack/smack_access.c 17.4 KB
a10e763b8   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
e114e4737   Casey Schaufler   Smack: Simplified...
2
3
4
  /*
   * Copyright (C) 2007 Casey Schaufler <casey@schaufler-ca.com>
   *
e114e4737   Casey Schaufler   Smack: Simplified...
5
6
   * Author:
   *      Casey Schaufler <casey@schaufler-ca.com>
e114e4737   Casey Schaufler   Smack: Simplified...
7
8
9
   */
  
  #include <linux/types.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
10
  #include <linux/slab.h>
e114e4737   Casey Schaufler   Smack: Simplified...
11
12
13
  #include <linux/fs.h>
  #include <linux/sched.h>
  #include "smack.h"
e114e4737   Casey Schaufler   Smack: Simplified...
14
  struct smack_known smack_known_huh = {
e114e4737   Casey Schaufler   Smack: Simplified...
15
16
  	.smk_known	= "?",
  	.smk_secid	= 2,
e114e4737   Casey Schaufler   Smack: Simplified...
17
18
19
  };
  
  struct smack_known smack_known_hat = {
e114e4737   Casey Schaufler   Smack: Simplified...
20
21
  	.smk_known	= "^",
  	.smk_secid	= 3,
e114e4737   Casey Schaufler   Smack: Simplified...
22
23
24
  };
  
  struct smack_known smack_known_star = {
e114e4737   Casey Schaufler   Smack: Simplified...
25
26
  	.smk_known	= "*",
  	.smk_secid	= 4,
e114e4737   Casey Schaufler   Smack: Simplified...
27
28
29
  };
  
  struct smack_known smack_known_floor = {
e114e4737   Casey Schaufler   Smack: Simplified...
30
31
  	.smk_known	= "_",
  	.smk_secid	= 5,
e114e4737   Casey Schaufler   Smack: Simplified...
32
  };
6d3dc07cb   Casey Schaufler   smack: Add suppor...
33
  struct smack_known smack_known_web = {
6d3dc07cb   Casey Schaufler   smack: Add suppor...
34
35
  	.smk_known	= "@",
  	.smk_secid	= 7,
6d3dc07cb   Casey Schaufler   smack: Add suppor...
36
  };
7198e2eeb   Etienne Basset   smack: convert sm...
37
  LIST_HEAD(smack_known_list);
e114e4737   Casey Schaufler   Smack: Simplified...
38
39
40
41
42
43
  
  /*
   * The initial value needs to be bigger than any of the
   * known values above.
   */
  static u32 smack_next_secid = 10;
ecfcc53fe   Etienne Basset   smack: implement ...
44
45
46
47
48
  /*
   * what events do we log
   * can be overwritten at run-time by /smack/logging
   */
  int log_policy = SMACK_AUDIT_DENIED;
e114e4737   Casey Schaufler   Smack: Simplified...
49
  /**
5c6d1125f   Jarkko Sakkinen   Smack: Transmute ...
50
51
52
   * smk_access_entry - look up matching access rule
   * @subject_label: a pointer to the subject's Smack label
   * @object_label: a pointer to the object's Smack label
7898e1f8e   Casey Schaufler   Subject: [PATCH] ...
53
   * @rule_list: the list of rules to search
5c6d1125f   Jarkko Sakkinen   Smack: Transmute ...
54
55
   *
   * This function looks up the subject/object pair in the
7898e1f8e   Casey Schaufler   Subject: [PATCH] ...
56
57
   * access rule list and returns the access mode. If no
   * entry is found returns -ENOENT.
5c6d1125f   Jarkko Sakkinen   Smack: Transmute ...
58
59
   *
   * NOTE:
5c6d1125f   Jarkko Sakkinen   Smack: Transmute ...
60
   *
272cd7a8c   Casey Schaufler   Smack: Rule list ...
61
62
63
64
65
66
67
68
69
70
71
72
   * Earlier versions of this function allowed for labels that
   * were not on the label list. This was done to allow for
   * labels to come over the network that had never been seen
   * before on this host. Unless the receiving socket has the
   * star label this will always result in a failure check. The
   * star labeled socket case is now handled in the networking
   * hooks so there is no case where the label is not on the
   * label list. Checking to see if the address of two labels
   * is the same is now a reliable test.
   *
   * Do the object check first because that is more
   * likely to differ.
c0ab6e56d   Casey Schaufler   Smack: Implement ...
73
74
   *
   * Allowing write access implies allowing locking.
5c6d1125f   Jarkko Sakkinen   Smack: Transmute ...
75
   */
7898e1f8e   Casey Schaufler   Subject: [PATCH] ...
76
77
  int smk_access_entry(char *subject_label, char *object_label,
  			struct list_head *rule_list)
5c6d1125f   Jarkko Sakkinen   Smack: Transmute ...
78
  {
7898e1f8e   Casey Schaufler   Subject: [PATCH] ...
79
  	int may = -ENOENT;
5c6d1125f   Jarkko Sakkinen   Smack: Transmute ...
80
  	struct smack_rule *srp;
7898e1f8e   Casey Schaufler   Subject: [PATCH] ...
81
  	list_for_each_entry_rcu(srp, rule_list, list) {
21c7eae21   Lukasz Pawelczyk   Make Smack operat...
82
  		if (srp->smk_object->smk_known == object_label &&
2f823ff8b   Casey Schaufler   Smack: Improve ac...
83
  		    srp->smk_subject->smk_known == subject_label) {
272cd7a8c   Casey Schaufler   Smack: Rule list ...
84
85
  			may = srp->smk_access;
  			break;
5c6d1125f   Jarkko Sakkinen   Smack: Transmute ...
86
87
  		}
  	}
5c6d1125f   Jarkko Sakkinen   Smack: Transmute ...
88

c0ab6e56d   Casey Schaufler   Smack: Implement ...
89
90
91
92
93
  	/*
  	 * MAY_WRITE implies MAY_LOCK.
  	 */
  	if ((may & MAY_WRITE) == MAY_WRITE)
  		may |= MAY_LOCK;
5c6d1125f   Jarkko Sakkinen   Smack: Transmute ...
94
95
96
97
  	return may;
  }
  
  /**
e114e4737   Casey Schaufler   Smack: Simplified...
98
   * smk_access - determine if a subject has a specific access to an object
21c7eae21   Lukasz Pawelczyk   Make Smack operat...
99
100
   * @subject: a pointer to the subject's Smack label entry
   * @object: a pointer to the object's Smack label entry
e114e4737   Casey Schaufler   Smack: Simplified...
101
   * @request: the access requested, in "MAY" format
ecfcc53fe   Etienne Basset   smack: implement ...
102
   * @a : a pointer to the audit data
e114e4737   Casey Schaufler   Smack: Simplified...
103
104
105
106
107
   *
   * This function looks up the subject/object pair in the
   * access rule list and returns 0 if the access is permitted,
   * non zero otherwise.
   *
272cd7a8c   Casey Schaufler   Smack: Rule list ...
108
   * Smack labels are shared on smack_list
e114e4737   Casey Schaufler   Smack: Simplified...
109
   */
21c7eae21   Lukasz Pawelczyk   Make Smack operat...
110
111
  int smk_access(struct smack_known *subject, struct smack_known *object,
  	       int request, struct smk_audit_info *a)
e114e4737   Casey Schaufler   Smack: Simplified...
112
  {
7898e1f8e   Casey Schaufler   Subject: [PATCH] ...
113
  	int may = MAY_NOT;
ecfcc53fe   Etienne Basset   smack: implement ...
114
  	int rc = 0;
e114e4737   Casey Schaufler   Smack: Simplified...
115
116
117
  
  	/*
  	 * Hardcoded comparisons.
bf4b2fee9   Casey Schaufler   Smack: Allow an u...
118
119
  	 */
  	/*
e114e4737   Casey Schaufler   Smack: Simplified...
120
121
  	 * A star subject can't access any object.
  	 */
21c7eae21   Lukasz Pawelczyk   Make Smack operat...
122
  	if (subject == &smack_known_star) {
ecfcc53fe   Etienne Basset   smack: implement ...
123
124
125
  		rc = -EACCES;
  		goto out_audit;
  	}
e114e4737   Casey Schaufler   Smack: Simplified...
126
  	/*
6d3dc07cb   Casey Schaufler   smack: Add suppor...
127
128
129
130
  	 * An internet object can be accessed by any subject.
  	 * Tasks cannot be assigned the internet label.
  	 * An internet subject can access any object.
  	 */
6c892df26   Casey Schaufler   Smack: Lock mode ...
131
  	if (object == &smack_known_web || subject == &smack_known_web)
ecfcc53fe   Etienne Basset   smack: implement ...
132
  		goto out_audit;
6d3dc07cb   Casey Schaufler   smack: Add suppor...
133
  	/*
e114e4737   Casey Schaufler   Smack: Simplified...
134
135
  	 * A star object can be accessed by any subject.
  	 */
21c7eae21   Lukasz Pawelczyk   Make Smack operat...
136
  	if (object == &smack_known_star)
ecfcc53fe   Etienne Basset   smack: implement ...
137
  		goto out_audit;
e114e4737   Casey Schaufler   Smack: Simplified...
138
139
140
141
  	/*
  	 * An object can be accessed in any way by a subject
  	 * with the same label.
  	 */
21c7eae21   Lukasz Pawelczyk   Make Smack operat...
142
  	if (subject->smk_known == object->smk_known)
ecfcc53fe   Etienne Basset   smack: implement ...
143
  		goto out_audit;
e114e4737   Casey Schaufler   Smack: Simplified...
144
  	/*
6c892df26   Casey Schaufler   Smack: Lock mode ...
145
146
  	 * A hat subject can read or lock any object.
  	 * A floor object can be read or locked by any subject.
e114e4737   Casey Schaufler   Smack: Simplified...
147
  	 */
6c892df26   Casey Schaufler   Smack: Lock mode ...
148
149
  	if ((request & MAY_ANYREAD) == request ||
  	    (request & MAY_LOCK) == request) {
21c7eae21   Lukasz Pawelczyk   Make Smack operat...
150
  		if (object == &smack_known_floor)
ecfcc53fe   Etienne Basset   smack: implement ...
151
  			goto out_audit;
21c7eae21   Lukasz Pawelczyk   Make Smack operat...
152
  		if (subject == &smack_known_hat)
ecfcc53fe   Etienne Basset   smack: implement ...
153
  			goto out_audit;
e114e4737   Casey Schaufler   Smack: Simplified...
154
155
156
157
158
  	}
  	/*
  	 * Beyond here an explicit relationship is required.
  	 * If the requested access is contained in the available
  	 * access (e.g. read is included in readwrite) it's
7898e1f8e   Casey Schaufler   Subject: [PATCH] ...
159
160
  	 * good. A negative response from smk_access_entry()
  	 * indicates there is no entry for this pair.
e114e4737   Casey Schaufler   Smack: Simplified...
161
  	 */
7898e1f8e   Casey Schaufler   Subject: [PATCH] ...
162
  	rcu_read_lock();
21c7eae21   Lukasz Pawelczyk   Make Smack operat...
163
164
  	may = smk_access_entry(subject->smk_known, object->smk_known,
  			       &subject->smk_rules);
7898e1f8e   Casey Schaufler   Subject: [PATCH] ...
165
  	rcu_read_unlock();
d166c8024   Casey Schaufler   Smack: Bring-up a...
166
167
  	if (may <= 0 || (request & may) != request) {
  		rc = -EACCES;
ecfcc53fe   Etienne Basset   smack: implement ...
168
  		goto out_audit;
d166c8024   Casey Schaufler   Smack: Bring-up a...
169
170
171
172
173
174
175
176
  	}
  #ifdef CONFIG_SECURITY_SMACK_BRINGUP
  	/*
  	 * Return a positive value if using bringup mode.
  	 * This allows the hooks to identify checks that
  	 * succeed because of "b" rules.
  	 */
  	if (may & MAY_BRINGUP)
bf4b2fee9   Casey Schaufler   Smack: Allow an u...
177
  		rc = SMACK_BRINGUP_ALLOW;
d166c8024   Casey Schaufler   Smack: Bring-up a...
178
  #endif
e114e4737   Casey Schaufler   Smack: Simplified...
179

ecfcc53fe   Etienne Basset   smack: implement ...
180
  out_audit:
bf4b2fee9   Casey Schaufler   Smack: Allow an u...
181
182
183
184
185
186
187
188
189
  
  #ifdef CONFIG_SECURITY_SMACK_BRINGUP
  	if (rc < 0) {
  		if (object == smack_unconfined)
  			rc = SMACK_UNCONFINED_OBJECT;
  		if (subject == smack_unconfined)
  			rc = SMACK_UNCONFINED_SUBJECT;
  	}
  #endif
ecfcc53fe   Etienne Basset   smack: implement ...
190
191
  #ifdef CONFIG_AUDIT
  	if (a)
21c7eae21   Lukasz Pawelczyk   Make Smack operat...
192
193
  		smack_log(subject->smk_known, object->smk_known,
  			  request, rc, a);
ecfcc53fe   Etienne Basset   smack: implement ...
194
  #endif
d166c8024   Casey Schaufler   Smack: Bring-up a...
195

ecfcc53fe   Etienne Basset   smack: implement ...
196
  	return rc;
e114e4737   Casey Schaufler   Smack: Simplified...
197
198
199
  }
  
  /**
959e6c7f1   Lukasz Pawelczyk   Smack: fix the su...
200
   * smk_tskacc - determine if a task has a specific access to an object
21c7eae21   Lukasz Pawelczyk   Make Smack operat...
201
202
   * @tsp: a pointer to the subject's task
   * @obj_known: a pointer to the object's label entry
251a2a958   Randy Dunlap   smack: fix lots o...
203
   * @mode: the access requested, in "MAY" format
ecfcc53fe   Etienne Basset   smack: implement ...
204
   * @a : common audit data
e114e4737   Casey Schaufler   Smack: Simplified...
205
   *
959e6c7f1   Lukasz Pawelczyk   Smack: fix the su...
206
   * This function checks the subject task's label/object label pair
e114e4737   Casey Schaufler   Smack: Simplified...
207
   * in the access rule list and returns 0 if the access is permitted,
959e6c7f1   Lukasz Pawelczyk   Smack: fix the su...
208
   * non zero otherwise. It allows that the task may have the capability
e114e4737   Casey Schaufler   Smack: Simplified...
209
210
   * to override the rules.
   */
21c7eae21   Lukasz Pawelczyk   Make Smack operat...
211
  int smk_tskacc(struct task_smack *tsp, struct smack_known *obj_known,
959e6c7f1   Lukasz Pawelczyk   Smack: fix the su...
212
  	       u32 mode, struct smk_audit_info *a)
e114e4737   Casey Schaufler   Smack: Simplified...
213
  {
21c7eae21   Lukasz Pawelczyk   Make Smack operat...
214
  	struct smack_known *sbj_known = smk_of_task(tsp);
7898e1f8e   Casey Schaufler   Subject: [PATCH] ...
215
  	int may;
e114e4737   Casey Schaufler   Smack: Simplified...
216
  	int rc;
7898e1f8e   Casey Schaufler   Subject: [PATCH] ...
217
218
219
  	/*
  	 * Check the global rule list
  	 */
21c7eae21   Lukasz Pawelczyk   Make Smack operat...
220
  	rc = smk_access(sbj_known, obj_known, mode, NULL);
d166c8024   Casey Schaufler   Smack: Bring-up a...
221
  	if (rc >= 0) {
7898e1f8e   Casey Schaufler   Subject: [PATCH] ...
222
223
224
225
  		/*
  		 * If there is an entry in the task's rule list
  		 * it can further restrict access.
  		 */
21c7eae21   Lukasz Pawelczyk   Make Smack operat...
226
227
228
  		may = smk_access_entry(sbj_known->smk_known,
  				       obj_known->smk_known,
  				       &tsp->smk_rules);
7898e1f8e   Casey Schaufler   Subject: [PATCH] ...
229
230
231
232
233
234
  		if (may < 0)
  			goto out_audit;
  		if ((mode & may) == mode)
  			goto out_audit;
  		rc = -EACCES;
  	}
e114e4737   Casey Schaufler   Smack: Simplified...
235

154462353   Casey Schaufler   smack: limit priv...
236
  	/*
1880eff77   Casey Schaufler   Smack: onlycap li...
237
  	 * Allow for priviliged to override policy.
154462353   Casey Schaufler   smack: limit priv...
238
  	 */
1880eff77   Casey Schaufler   Smack: onlycap li...
239
  	if (rc != 0 && smack_privileged(CAP_MAC_OVERRIDE))
7898e1f8e   Casey Schaufler   Subject: [PATCH] ...
240
  		rc = 0;
e114e4737   Casey Schaufler   Smack: Simplified...
241

ecfcc53fe   Etienne Basset   smack: implement ...
242
243
244
  out_audit:
  #ifdef CONFIG_AUDIT
  	if (a)
21c7eae21   Lukasz Pawelczyk   Make Smack operat...
245
246
  		smack_log(sbj_known->smk_known, obj_known->smk_known,
  			  mode, rc, a);
ecfcc53fe   Etienne Basset   smack: implement ...
247
  #endif
e114e4737   Casey Schaufler   Smack: Simplified...
248
249
  	return rc;
  }
959e6c7f1   Lukasz Pawelczyk   Smack: fix the su...
250
251
  /**
   * smk_curacc - determine if current has a specific access to an object
21c7eae21   Lukasz Pawelczyk   Make Smack operat...
252
   * @obj_known: a pointer to the object's Smack label entry
959e6c7f1   Lukasz Pawelczyk   Smack: fix the su...
253
254
255
256
257
258
259
260
   * @mode: the access requested, in "MAY" format
   * @a : common audit data
   *
   * This function checks the current subject label/object label pair
   * in the access rule list and returns 0 if the access is permitted,
   * non zero otherwise. It allows that current may have the capability
   * to override the rules.
   */
21c7eae21   Lukasz Pawelczyk   Make Smack operat...
261
262
  int smk_curacc(struct smack_known *obj_known,
  	       u32 mode, struct smk_audit_info *a)
959e6c7f1   Lukasz Pawelczyk   Smack: fix the su...
263
  {
b17103a8b   Casey Schaufler   Smack: Abstract u...
264
  	struct task_smack *tsp = smack_cred(current_cred());
959e6c7f1   Lukasz Pawelczyk   Smack: fix the su...
265

21c7eae21   Lukasz Pawelczyk   Make Smack operat...
266
  	return smk_tskacc(tsp, obj_known, mode, a);
959e6c7f1   Lukasz Pawelczyk   Smack: fix the su...
267
  }
ecfcc53fe   Etienne Basset   smack: implement ...
268
269
270
271
272
273
274
275
276
277
278
  #ifdef CONFIG_AUDIT
  /**
   * smack_str_from_perm : helper to transalate an int to a
   * readable string
   * @string : the string to fill
   * @access : the int
   *
   */
  static inline void smack_str_from_perm(char *string, int access)
  {
  	int i = 0;
c0ab6e56d   Casey Schaufler   Smack: Implement ...
279

ecfcc53fe   Etienne Basset   smack: implement ...
280
281
282
283
284
285
286
287
  	if (access & MAY_READ)
  		string[i++] = 'r';
  	if (access & MAY_WRITE)
  		string[i++] = 'w';
  	if (access & MAY_EXEC)
  		string[i++] = 'x';
  	if (access & MAY_APPEND)
  		string[i++] = 'a';
a87d79ad7   Rafal Krypa   Smack: add missin...
288
289
  	if (access & MAY_TRANSMUTE)
  		string[i++] = 't';
c0ab6e56d   Casey Schaufler   Smack: Implement ...
290
291
  	if (access & MAY_LOCK)
  		string[i++] = 'l';
ecfcc53fe   Etienne Basset   smack: implement ...
292
293
294
295
296
297
298
299
300
301
302
303
  	string[i] = '\0';
  }
  /**
   * smack_log_callback - SMACK specific information
   * will be called by generic audit code
   * @ab : the audit_buffer
   * @a  : audit_data
   *
   */
  static void smack_log_callback(struct audit_buffer *ab, void *a)
  {
  	struct common_audit_data *ad = a;
3b3b0e4fc   Eric Paris   LSM: shrink sizeo...
304
  	struct smack_audit_data *sad = ad->smack_audit_data;
ed5215a21   Thomas Liu   Move variable fun...
305
  	audit_log_format(ab, "lsm=SMACK fn=%s action=%s",
3b3b0e4fc   Eric Paris   LSM: shrink sizeo...
306
  			 ad->smack_audit_data->function,
ecfcc53fe   Etienne Basset   smack: implement ...
307
308
309
310
311
  			 sad->result ? "denied" : "granted");
  	audit_log_format(ab, " subject=");
  	audit_log_untrustedstring(ab, sad->subject);
  	audit_log_format(ab, " object=");
  	audit_log_untrustedstring(ab, sad->object);
668678185   Lukasz Pawelczyk   Smack: adds smack...
312
313
314
315
  	if (sad->request[0] == '\0')
  		audit_log_format(ab, " labels_differ");
  	else
  		audit_log_format(ab, " requested=%s", sad->request);
ecfcc53fe   Etienne Basset   smack: implement ...
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
  }
  
  /**
   *  smack_log - Audit the granting or denial of permissions.
   *  @subject_label : smack label of the requester
   *  @object_label  : smack label of the object being accessed
   *  @request: requested permissions
   *  @result: result from smk_access
   *  @a:  auxiliary audit data
   *
   * Audit the granting or denial of permissions in accordance
   * with the policy.
   */
  void smack_log(char *subject_label, char *object_label, int request,
  	       int result, struct smk_audit_info *ad)
  {
bf4b2fee9   Casey Schaufler   Smack: Allow an u...
332
333
334
  #ifdef CONFIG_SECURITY_SMACK_BRINGUP
  	char request_buffer[SMK_NUM_ACCESS_TYPE + 5];
  #else
ecfcc53fe   Etienne Basset   smack: implement ...
335
  	char request_buffer[SMK_NUM_ACCESS_TYPE + 1];
bf4b2fee9   Casey Schaufler   Smack: Allow an u...
336
  #endif
ecfcc53fe   Etienne Basset   smack: implement ...
337
338
339
340
  	struct smack_audit_data *sad;
  	struct common_audit_data *a = &ad->a;
  
  	/* check if we have to log the current event */
bf4b2fee9   Casey Schaufler   Smack: Allow an u...
341
  	if (result < 0 && (log_policy & SMACK_AUDIT_DENIED) == 0)
ecfcc53fe   Etienne Basset   smack: implement ...
342
343
344
  		return;
  	if (result == 0 && (log_policy & SMACK_AUDIT_ACCEPT) == 0)
  		return;
3b3b0e4fc   Eric Paris   LSM: shrink sizeo...
345
346
347
348
  	sad = a->smack_audit_data;
  
  	if (sad->function == NULL)
  		sad->function = "unknown";
ecfcc53fe   Etienne Basset   smack: implement ...
349
350
  
  	/* end preparing the audit data */
ecfcc53fe   Etienne Basset   smack: implement ...
351
352
353
  	smack_str_from_perm(request_buffer, request);
  	sad->subject = subject_label;
  	sad->object  = object_label;
bf4b2fee9   Casey Schaufler   Smack: Allow an u...
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
  #ifdef CONFIG_SECURITY_SMACK_BRINGUP
  	/*
  	 * The result may be positive in bringup mode.
  	 * A positive result is an allow, but not for normal reasons.
  	 * Mark it as successful, but don't filter it out even if
  	 * the logging policy says to do so.
  	 */
  	if (result == SMACK_UNCONFINED_SUBJECT)
  		strcat(request_buffer, "(US)");
  	else if (result == SMACK_UNCONFINED_OBJECT)
  		strcat(request_buffer, "(UO)");
  
  	if (result > 0)
  		result = 0;
  #endif
ecfcc53fe   Etienne Basset   smack: implement ...
369
370
  	sad->request = request_buffer;
  	sad->result  = result;
ecfcc53fe   Etienne Basset   smack: implement ...
371

b61c37f57   Linus Torvalds   lsm_audit: don't ...
372
  	common_lsm_audit(a, smack_log_callback, NULL);
ecfcc53fe   Etienne Basset   smack: implement ...
373
374
375
376
377
378
379
  }
  #else /* #ifdef CONFIG_AUDIT */
  void smack_log(char *subject_label, char *object_label, int request,
                 int result, struct smk_audit_info *ad)
  {
  }
  #endif
f7112e6c9   Casey Schaufler   Smack: allow for ...
380
  DEFINE_MUTEX(smack_known_lock);
e114e4737   Casey Schaufler   Smack: Simplified...
381

4d7cf4a1f   Tomasz Stanislawski   security: smack: ...
382
383
384
385
386
387
388
389
390
391
392
  struct hlist_head smack_known_hash[SMACK_HASH_SLOTS];
  
  /**
   * smk_insert_entry - insert a smack label into a hash map,
   *
   * this function must be called under smack_known_lock
   */
  void smk_insert_entry(struct smack_known *skp)
  {
  	unsigned int hash;
  	struct hlist_head *head;
8387ff257   Linus Torvalds   vfs: make the str...
393
  	hash = full_name_hash(NULL, skp->smk_known, strlen(skp->smk_known));
4d7cf4a1f   Tomasz Stanislawski   security: smack: ...
394
395
396
397
398
  	head = &smack_known_hash[hash & (SMACK_HASH_SLOTS - 1)];
  
  	hlist_add_head_rcu(&skp->smk_hashed, head);
  	list_add_rcu(&skp->list, &smack_known_list);
  }
e114e4737   Casey Schaufler   Smack: Simplified...
399
  /**
272cd7a8c   Casey Schaufler   Smack: Rule list ...
400
401
402
403
   * smk_find_entry - find a label on the list, return the list entry
   * @string: a text string that might be a Smack label
   *
   * Returns a pointer to the entry in the label list that
e774ad683   Lukasz Pawelczyk   smack: pass error...
404
   * matches the passed string or NULL if not found.
272cd7a8c   Casey Schaufler   Smack: Rule list ...
405
406
407
   */
  struct smack_known *smk_find_entry(const char *string)
  {
4d7cf4a1f   Tomasz Stanislawski   security: smack: ...
408
409
  	unsigned int hash;
  	struct hlist_head *head;
272cd7a8c   Casey Schaufler   Smack: Rule list ...
410
  	struct smack_known *skp;
8387ff257   Linus Torvalds   vfs: make the str...
411
  	hash = full_name_hash(NULL, string, strlen(string));
4d7cf4a1f   Tomasz Stanislawski   security: smack: ...
412
413
414
  	head = &smack_known_hash[hash & (SMACK_HASH_SLOTS - 1)];
  
  	hlist_for_each_entry_rcu(skp, head, smk_hashed)
f7112e6c9   Casey Schaufler   Smack: allow for ...
415
  		if (strcmp(skp->smk_known, string) == 0)
272cd7a8c   Casey Schaufler   Smack: Rule list ...
416
  			return skp;
272cd7a8c   Casey Schaufler   Smack: Rule list ...
417
418
419
420
421
  
  	return NULL;
  }
  
  /**
0e94ae17c   Jarkko Sakkinen   Smack: allow to a...
422
423
   * smk_parse_smack - parse smack label from a text string
   * @string: a text string that might contain a Smack label
e114e4737   Casey Schaufler   Smack: Simplified...
424
   * @len: the maximum size, or zero if it is NULL terminated.
f7112e6c9   Casey Schaufler   Smack: allow for ...
425
   *
e774ad683   Lukasz Pawelczyk   smack: pass error...
426
   * Returns a pointer to the clean label or an error code.
e114e4737   Casey Schaufler   Smack: Simplified...
427
   */
f7112e6c9   Casey Schaufler   Smack: allow for ...
428
  char *smk_parse_smack(const char *string, int len)
e114e4737   Casey Schaufler   Smack: Simplified...
429
  {
f7112e6c9   Casey Schaufler   Smack: allow for ...
430
  	char *smack;
e114e4737   Casey Schaufler   Smack: Simplified...
431
  	int i;
f7112e6c9   Casey Schaufler   Smack: allow for ...
432
433
434
435
436
437
438
439
440
  	if (len <= 0)
  		len = strlen(string) + 1;
  
  	/*
  	 * Reserve a leading '-' as an indicator that
  	 * this isn't a label, but an option to interfaces
  	 * including /smack/cipso and /smack/cipso2
  	 */
  	if (string[0] == '-')
e774ad683   Lukasz Pawelczyk   smack: pass error...
441
  		return ERR_PTR(-EINVAL);
f7112e6c9   Casey Schaufler   Smack: allow for ...
442
443
444
445
446
447
448
  
  	for (i = 0; i < len; i++)
  		if (string[i] > '~' || string[i] <= ' ' || string[i] == '/' ||
  		    string[i] == '"' || string[i] == '\\' || string[i] == '\'')
  			break;
  
  	if (i == 0 || i >= SMK_LONGLABEL)
e774ad683   Lukasz Pawelczyk   smack: pass error...
449
  		return ERR_PTR(-EINVAL);
f7112e6c9   Casey Schaufler   Smack: allow for ...
450

e5bfad3d7   Eric Biggers   smack: use GFP_NO...
451
  	smack = kzalloc(i + 1, GFP_NOFS);
e774ad683   Lukasz Pawelczyk   smack: pass error...
452
453
454
455
  	if (smack == NULL)
  		return ERR_PTR(-ENOMEM);
  
  	strncpy(smack, string, i);
5c1b66240   Andrey Ryabinin   security: smack: ...
456

f7112e6c9   Casey Schaufler   Smack: allow for ...
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
  	return smack;
  }
  
  /**
   * smk_netlbl_mls - convert a catset to netlabel mls categories
   * @catset: the Smack categories
   * @sap: where to put the netlabel categories
   *
   * Allocates and fills attr.mls
   * Returns 0 on success, error code on failure.
   */
  int smk_netlbl_mls(int level, char *catset, struct netlbl_lsm_secattr *sap,
  			int len)
  {
  	unsigned char *cp;
  	unsigned char m;
  	int cat;
  	int rc;
  	int byte;
  
  	sap->flags |= NETLBL_SECATTR_MLS_CAT;
  	sap->attr.mls.lvl = level;
4b8feff25   Paul Moore   netlabel: fix the...
479
  	sap->attr.mls.cat = NULL;
f7112e6c9   Casey Schaufler   Smack: allow for ...
480
481
482
483
484
  
  	for (cat = 1, cp = catset, byte = 0; byte < len; cp++, byte++)
  		for (m = 0x80; m != 0; m >>= 1, cat++) {
  			if ((m & *cp) == 0)
  				continue;
4fbe63d1c   Paul Moore   netlabel: shorter...
485
  			rc = netlbl_catmap_setbit(&sap->attr.mls.cat,
e5bfad3d7   Eric Biggers   smack: use GFP_NO...
486
  						  cat, GFP_NOFS);
f7112e6c9   Casey Schaufler   Smack: allow for ...
487
  			if (rc < 0) {
4fbe63d1c   Paul Moore   netlabel: shorter...
488
  				netlbl_catmap_free(sap->attr.mls.cat);
f7112e6c9   Casey Schaufler   Smack: allow for ...
489
490
491
492
493
  				return rc;
  			}
  		}
  
  	return 0;
0e94ae17c   Jarkko Sakkinen   Smack: allow to a...
494
495
496
  }
  
  /**
322dd63c7   Casey Schaufler   Smack: Use the ne...
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
   * smack_populate_secattr - fill in the smack_known netlabel information
   * @skp: pointer to the structure to fill
   *
   * Populate the netlabel secattr structure for a Smack label.
   *
   * Returns 0 unless creating the category mapping fails
   */
  int smack_populate_secattr(struct smack_known *skp)
  {
  	int slen;
  
  	skp->smk_netlabel.attr.secid = skp->smk_secid;
  	skp->smk_netlabel.domain = skp->smk_known;
  	skp->smk_netlabel.cache = netlbl_secattr_cache_alloc(GFP_ATOMIC);
  	if (skp->smk_netlabel.cache != NULL) {
  		skp->smk_netlabel.flags |= NETLBL_SECATTR_CACHE;
  		skp->smk_netlabel.cache->free = NULL;
  		skp->smk_netlabel.cache->data = skp;
  	}
  	skp->smk_netlabel.flags |= NETLBL_SECATTR_SECID |
  				   NETLBL_SECATTR_MLS_LVL |
  				   NETLBL_SECATTR_DOMAIN;
  	/*
  	 * If direct labeling works use it.
  	 * Otherwise use mapped labeling.
  	 */
  	slen = strlen(skp->smk_known);
  	if (slen < SMK_CIPSOLEN)
  		return smk_netlbl_mls(smack_cipso_direct, skp->smk_known,
  				      &skp->smk_netlabel, slen);
  
  	return smk_netlbl_mls(smack_cipso_mapped, (char *)&skp->smk_secid,
  			      &skp->smk_netlabel, sizeof(skp->smk_secid));
  }
  
  /**
0e94ae17c   Jarkko Sakkinen   Smack: allow to a...
533
534
535
536
537
   * smk_import_entry - import a label, return the list entry
   * @string: a text string that might be a Smack label
   * @len: the maximum size, or zero if it is NULL terminated.
   *
   * Returns a pointer to the entry in the label list that
e774ad683   Lukasz Pawelczyk   smack: pass error...
538
539
   * matches the passed string, adding it if necessary,
   * or an error code.
0e94ae17c   Jarkko Sakkinen   Smack: allow to a...
540
541
542
543
   */
  struct smack_known *smk_import_entry(const char *string, int len)
  {
  	struct smack_known *skp;
f7112e6c9   Casey Schaufler   Smack: allow for ...
544
  	char *smack;
f7112e6c9   Casey Schaufler   Smack: allow for ...
545
  	int rc;
e114e4737   Casey Schaufler   Smack: Simplified...
546

f7112e6c9   Casey Schaufler   Smack: allow for ...
547
  	smack = smk_parse_smack(string, len);
e774ad683   Lukasz Pawelczyk   smack: pass error...
548
549
  	if (IS_ERR(smack))
  		return ERR_CAST(smack);
e114e4737   Casey Schaufler   Smack: Simplified...
550
551
  
  	mutex_lock(&smack_known_lock);
272cd7a8c   Casey Schaufler   Smack: Rule list ...
552
  	skp = smk_find_entry(smack);
f7112e6c9   Casey Schaufler   Smack: allow for ...
553
554
  	if (skp != NULL)
  		goto freeout;
e114e4737   Casey Schaufler   Smack: Simplified...
555

e5bfad3d7   Eric Biggers   smack: use GFP_NO...
556
  	skp = kzalloc(sizeof(*skp), GFP_NOFS);
e774ad683   Lukasz Pawelczyk   smack: pass error...
557
558
  	if (skp == NULL) {
  		skp = ERR_PTR(-ENOMEM);
f7112e6c9   Casey Schaufler   Smack: allow for ...
559
  		goto freeout;
e774ad683   Lukasz Pawelczyk   smack: pass error...
560
  	}
e114e4737   Casey Schaufler   Smack: Simplified...
561

f7112e6c9   Casey Schaufler   Smack: allow for ...
562
563
  	skp->smk_known = smack;
  	skp->smk_secid = smack_next_secid++;
f7112e6c9   Casey Schaufler   Smack: allow for ...
564

322dd63c7   Casey Schaufler   Smack: Use the ne...
565
  	rc = smack_populate_secattr(skp);
f7112e6c9   Casey Schaufler   Smack: allow for ...
566
567
568
569
570
571
572
  	if (rc >= 0) {
  		INIT_LIST_HEAD(&skp->smk_rules);
  		mutex_init(&skp->smk_rules_lock);
  		/*
  		 * Make sure that the entry is actually
  		 * filled before putting it on the list.
  		 */
4d7cf4a1f   Tomasz Stanislawski   security: smack: ...
573
  		smk_insert_entry(skp);
f7112e6c9   Casey Schaufler   Smack: allow for ...
574
575
  		goto unlockout;
  	}
f7112e6c9   Casey Schaufler   Smack: allow for ...
576
  	kfree(skp);
e774ad683   Lukasz Pawelczyk   smack: pass error...
577
  	skp = ERR_PTR(rc);
f7112e6c9   Casey Schaufler   Smack: allow for ...
578
579
580
  freeout:
  	kfree(smack);
  unlockout:
e114e4737   Casey Schaufler   Smack: Simplified...
581
582
583
584
585
586
  	mutex_unlock(&smack_known_lock);
  
  	return skp;
  }
  
  /**
e114e4737   Casey Schaufler   Smack: Simplified...
587
588
589
   * smack_from_secid - find the Smack label associated with a secid
   * @secid: an integer that might be associated with a Smack label
   *
2f823ff8b   Casey Schaufler   Smack: Improve ac...
590
   * Returns a pointer to the appropriate Smack label entry if there is one,
e114e4737   Casey Schaufler   Smack: Simplified...
591
592
   * otherwise a pointer to the invalid Smack label.
   */
2f823ff8b   Casey Schaufler   Smack: Improve ac...
593
  struct smack_known *smack_from_secid(const u32 secid)
e114e4737   Casey Schaufler   Smack: Simplified...
594
595
  {
  	struct smack_known *skp;
7198e2eeb   Etienne Basset   smack: convert sm...
596
597
598
599
  	rcu_read_lock();
  	list_for_each_entry_rcu(skp, &smack_known_list, list) {
  		if (skp->smk_secid == secid) {
  			rcu_read_unlock();
2f823ff8b   Casey Schaufler   Smack: Improve ac...
600
  			return skp;
7198e2eeb   Etienne Basset   smack: convert sm...
601
602
  		}
  	}
e114e4737   Casey Schaufler   Smack: Simplified...
603
604
605
606
607
  
  	/*
  	 * If we got this far someone asked for the translation
  	 * of a secid that is not on the list.
  	 */
7198e2eeb   Etienne Basset   smack: convert sm...
608
  	rcu_read_unlock();
152f91d4d   Casey Schaufler   Smack: Remove unn...
609
  	return &smack_known_huh;
e114e4737   Casey Schaufler   Smack: Simplified...
610
  }
c0d77c884   Rafal Krypa   Smack: allow mult...
611
612
613
614
615
616
617
618
619
620
  
  /*
   * Unless a process is running with one of these labels
   * even having CAP_MAC_OVERRIDE isn't enough to grant
   * privilege to violate MAC policy. If no labels are
   * designated (the empty list case) capabilities apply to
   * everyone.
   */
  LIST_HEAD(smack_onlycap_list);
  DEFINE_MUTEX(smack_onlycap_lock);
d19dfe58b   Casey Schaufler   Smack: Privilege ...
621
622
623
624
625
  /**
   * smack_privileged_cred - are all privilege requirements met by cred
   * @cap: The requested capability
   * @cred: the credential to use
   *
c0d77c884   Rafal Krypa   Smack: allow mult...
626
627
628
   * Is the task privileged and allowed to be privileged
   * by the onlycap rule.
   *
f28e783ff   Casey Schaufler   Smack: Use cap_ca...
629
   * Returns true if the task is allowed to be privileged, false if it's not.
c0d77c884   Rafal Krypa   Smack: allow mult...
630
   */
d19dfe58b   Casey Schaufler   Smack: Privilege ...
631
  bool smack_privileged_cred(int cap, const struct cred *cred)
c0d77c884   Rafal Krypa   Smack: allow mult...
632
  {
b17103a8b   Casey Schaufler   Smack: Abstract u...
633
  	struct task_smack *tsp = smack_cred(cred);
d19dfe58b   Casey Schaufler   Smack: Privilege ...
634
  	struct smack_known *skp = tsp->smk_task;
38416e539   Zbigniew Jasinski   Smack: limited ca...
635
  	struct smack_known_list_elem *sklep;
f28e783ff   Casey Schaufler   Smack: Use cap_ca...
636
  	int rc;
c0d77c884   Rafal Krypa   Smack: allow mult...
637

c1a85a00e   Micah Morton   LSM: generalize f...
638
  	rc = cap_capable(cred, &init_user_ns, cap, CAP_OPT_NONE);
f28e783ff   Casey Schaufler   Smack: Use cap_ca...
639
640
  	if (rc)
  		return false;
c0d77c884   Rafal Krypa   Smack: allow mult...
641
642
643
644
  
  	rcu_read_lock();
  	if (list_empty(&smack_onlycap_list)) {
  		rcu_read_unlock();
f28e783ff   Casey Schaufler   Smack: Use cap_ca...
645
  		return true;
c0d77c884   Rafal Krypa   Smack: allow mult...
646
  	}
38416e539   Zbigniew Jasinski   Smack: limited ca...
647
648
  	list_for_each_entry_rcu(sklep, &smack_onlycap_list, list) {
  		if (sklep->smk_label == skp) {
c0d77c884   Rafal Krypa   Smack: allow mult...
649
  			rcu_read_unlock();
f28e783ff   Casey Schaufler   Smack: Use cap_ca...
650
  			return true;
c0d77c884   Rafal Krypa   Smack: allow mult...
651
652
653
  		}
  	}
  	rcu_read_unlock();
f28e783ff   Casey Schaufler   Smack: Use cap_ca...
654
  	return false;
c0d77c884   Rafal Krypa   Smack: allow mult...
655
  }
d19dfe58b   Casey Schaufler   Smack: Privilege ...
656
657
658
659
660
661
662
663
664
665
666
667
668
  
  /**
   * smack_privileged - are all privilege requirements met
   * @cap: The requested capability
   *
   * Is the task privileged and allowed to be privileged
   * by the onlycap rule.
   *
   * Returns true if the task is allowed to be privileged, false if it's not.
   */
  bool smack_privileged(int cap)
  {
  	/*
8f939abd8   Casey Schaufler   Smack: Handle io_...
669
670
  	 * Kernel threads may not have credentials we can use.
  	 * The io_uring kernel threads do have reliable credentials.
d19dfe58b   Casey Schaufler   Smack: Privilege ...
671
  	 */
8f939abd8   Casey Schaufler   Smack: Handle io_...
672
  	if ((current->flags & (PF_KTHREAD | PF_IO_WORKER)) == PF_KTHREAD)
d19dfe58b   Casey Schaufler   Smack: Privilege ...
673
674
675
676
  		return true;
  
  	return smack_privileged_cred(cap, current_cred());
  }