Blame view

kernel/cred.c 14.5 KB
98870ab0a   David Howells   CRED: Documentation
1
  /* Task credentials management - see Documentation/credentials.txt
f1752eec6   David Howells   CRED: Detach the ...
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
   *
   * Copyright (C) 2008 Red Hat, Inc. All Rights Reserved.
   * Written by David Howells (dhowells@redhat.com)
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public Licence
   * as published by the Free Software Foundation; either version
   * 2 of the Licence, or (at your option) any later version.
   */
  #include <linux/module.h>
  #include <linux/cred.h>
  #include <linux/sched.h>
  #include <linux/key.h>
  #include <linux/keyctl.h>
  #include <linux/init_task.h>
  #include <linux/security.h>
d84f4f992   David Howells   CRED: Inaugurate ...
18
19
20
21
  #include <linux/cn_proc.h>
  #include "cred-internals.h"
  
  static struct kmem_cache *cred_jar;
f1752eec6   David Howells   CRED: Detach the ...
22
23
  
  /*
bb952bb98   David Howells   CRED: Separate pe...
24
25
26
27
28
29
30
31
32
33
34
   * The common credentials for the initial task's thread group
   */
  #ifdef CONFIG_KEYS
  static struct thread_group_cred init_tgcred = {
  	.usage	= ATOMIC_INIT(2),
  	.tgid	= 0,
  	.lock	= SPIN_LOCK_UNLOCKED,
  };
  #endif
  
  /*
f1752eec6   David Howells   CRED: Detach the ...
35
36
37
   * The initial credentials for the initial task
   */
  struct cred init_cred = {
3b11a1dec   David Howells   CRED: Differentia...
38
  	.usage			= ATOMIC_INIT(4),
f1752eec6   David Howells   CRED: Detach the ...
39
40
41
42
43
44
45
  	.securebits		= SECUREBITS_DEFAULT,
  	.cap_inheritable	= CAP_INIT_INH_SET,
  	.cap_permitted		= CAP_FULL_SET,
  	.cap_effective		= CAP_INIT_EFF_SET,
  	.cap_bset		= CAP_INIT_BSET,
  	.user			= INIT_USER,
  	.group_info		= &init_groups,
bb952bb98   David Howells   CRED: Separate pe...
46
47
48
  #ifdef CONFIG_KEYS
  	.tgcred			= &init_tgcred,
  #endif
f1752eec6   David Howells   CRED: Detach the ...
49
50
51
  };
  
  /*
bb952bb98   David Howells   CRED: Separate pe...
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
   * Dispose of the shared task group credentials
   */
  #ifdef CONFIG_KEYS
  static void release_tgcred_rcu(struct rcu_head *rcu)
  {
  	struct thread_group_cred *tgcred =
  		container_of(rcu, struct thread_group_cred, rcu);
  
  	BUG_ON(atomic_read(&tgcred->usage) != 0);
  
  	key_put(tgcred->session_keyring);
  	key_put(tgcred->process_keyring);
  	kfree(tgcred);
  }
  #endif
  
  /*
   * Release a set of thread group credentials.
   */
a6f76f23d   David Howells   CRED: Make execve...
71
  static void release_tgcred(struct cred *cred)
bb952bb98   David Howells   CRED: Separate pe...
72
73
74
75
76
77
78
79
80
81
  {
  #ifdef CONFIG_KEYS
  	struct thread_group_cred *tgcred = cred->tgcred;
  
  	if (atomic_dec_and_test(&tgcred->usage))
  		call_rcu(&tgcred->rcu, release_tgcred_rcu);
  #endif
  }
  
  /*
f1752eec6   David Howells   CRED: Detach the ...
82
83
84
85
86
   * The RCU callback to actually dispose of a set of credentials
   */
  static void put_cred_rcu(struct rcu_head *rcu)
  {
  	struct cred *cred = container_of(rcu, struct cred, rcu);
d84f4f992   David Howells   CRED: Inaugurate ...
87
88
89
90
  	if (atomic_read(&cred->usage) != 0)
  		panic("CRED: put_cred_rcu() sees %p with usage %d
  ",
  		      cred, atomic_read(&cred->usage));
f1752eec6   David Howells   CRED: Detach the ...
91

d84f4f992   David Howells   CRED: Inaugurate ...
92
  	security_cred_free(cred);
f1752eec6   David Howells   CRED: Detach the ...
93
94
  	key_put(cred->thread_keyring);
  	key_put(cred->request_key_auth);
bb952bb98   David Howells   CRED: Separate pe...
95
  	release_tgcred(cred);
f1752eec6   David Howells   CRED: Detach the ...
96
97
  	put_group_info(cred->group_info);
  	free_uid(cred->user);
d84f4f992   David Howells   CRED: Inaugurate ...
98
  	kmem_cache_free(cred_jar, cred);
f1752eec6   David Howells   CRED: Detach the ...
99
100
101
102
  }
  
  /**
   * __put_cred - Destroy a set of credentials
d84f4f992   David Howells   CRED: Inaugurate ...
103
   * @cred: The record to release
f1752eec6   David Howells   CRED: Detach the ...
104
105
106
107
108
   *
   * Destroy a set of credentials on which no references remain.
   */
  void __put_cred(struct cred *cred)
  {
d84f4f992   David Howells   CRED: Inaugurate ...
109
  	BUG_ON(atomic_read(&cred->usage) != 0);
f1752eec6   David Howells   CRED: Detach the ...
110
111
112
  	call_rcu(&cred->rcu, put_cred_rcu);
  }
  EXPORT_SYMBOL(__put_cred);
d84f4f992   David Howells   CRED: Inaugurate ...
113
114
115
116
117
118
119
120
  /**
   * prepare_creds - Prepare a new set of credentials for modification
   *
   * Prepare a new set of task credentials for modification.  A task's creds
   * shouldn't generally be modified directly, therefore this function is used to
   * prepare a new copy, which the caller then modifies and then commits by
   * calling commit_creds().
   *
3b11a1dec   David Howells   CRED: Differentia...
121
122
   * Preparation involves making a copy of the objective creds for modification.
   *
d84f4f992   David Howells   CRED: Inaugurate ...
123
124
125
126
127
128
129
130
131
   * Returns a pointer to the new creds-to-be if successful, NULL otherwise.
   *
   * Call commit_creds() or abort_creds() to clean up.
   */
  struct cred *prepare_creds(void)
  {
  	struct task_struct *task = current;
  	const struct cred *old;
  	struct cred *new;
3b11a1dec   David Howells   CRED: Differentia...
132
  	BUG_ON(atomic_read(&task->real_cred->usage) < 1);
d84f4f992   David Howells   CRED: Inaugurate ...
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
  
  	new = kmem_cache_alloc(cred_jar, GFP_KERNEL);
  	if (!new)
  		return NULL;
  
  	old = task->cred;
  	memcpy(new, old, sizeof(struct cred));
  
  	atomic_set(&new->usage, 1);
  	get_group_info(new->group_info);
  	get_uid(new->user);
  
  #ifdef CONFIG_KEYS
  	key_get(new->thread_keyring);
  	key_get(new->request_key_auth);
  	atomic_inc(&new->tgcred->usage);
  #endif
  
  #ifdef CONFIG_SECURITY
  	new->security = NULL;
  #endif
  
  	if (security_prepare_creds(new, old, GFP_KERNEL) < 0)
  		goto error;
  	return new;
  
  error:
  	abort_creds(new);
  	return NULL;
  }
  EXPORT_SYMBOL(prepare_creds);
  
  /*
a6f76f23d   David Howells   CRED: Make execve...
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
   * Prepare credentials for current to perform an execve()
   * - The caller must hold current->cred_exec_mutex
   */
  struct cred *prepare_exec_creds(void)
  {
  	struct thread_group_cred *tgcred = NULL;
  	struct cred *new;
  
  #ifdef CONFIG_KEYS
  	tgcred = kmalloc(sizeof(*tgcred), GFP_KERNEL);
  	if (!tgcred)
  		return NULL;
  #endif
  
  	new = prepare_creds();
  	if (!new) {
  		kfree(tgcred);
  		return new;
  	}
  
  #ifdef CONFIG_KEYS
  	/* newly exec'd tasks don't get a thread keyring */
  	key_put(new->thread_keyring);
  	new->thread_keyring = NULL;
  
  	/* create a new per-thread-group creds for all this set of threads to
  	 * share */
  	memcpy(tgcred, new->tgcred, sizeof(struct thread_group_cred));
  
  	atomic_set(&tgcred->usage, 1);
  	spin_lock_init(&tgcred->lock);
  
  	/* inherit the session keyring; new process keyring */
  	key_get(tgcred->session_keyring);
  	tgcred->process_keyring = NULL;
  
  	release_tgcred(new);
  	new->tgcred = tgcred;
  #endif
  
  	return new;
  }
  
  /*
d84f4f992   David Howells   CRED: Inaugurate ...
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
   * prepare new credentials for the usermode helper dispatcher
   */
  struct cred *prepare_usermodehelper_creds(void)
  {
  #ifdef CONFIG_KEYS
  	struct thread_group_cred *tgcred = NULL;
  #endif
  	struct cred *new;
  
  #ifdef CONFIG_KEYS
  	tgcred = kzalloc(sizeof(*new->tgcred), GFP_ATOMIC);
  	if (!tgcred)
  		return NULL;
  #endif
  
  	new = kmem_cache_alloc(cred_jar, GFP_ATOMIC);
  	if (!new)
  		return NULL;
  
  	memcpy(new, &init_cred, sizeof(struct cred));
  
  	atomic_set(&new->usage, 1);
  	get_group_info(new->group_info);
  	get_uid(new->user);
  
  #ifdef CONFIG_KEYS
  	new->thread_keyring = NULL;
  	new->request_key_auth = NULL;
  	new->jit_keyring = KEY_REQKEY_DEFL_DEFAULT;
  
  	atomic_set(&tgcred->usage, 1);
  	spin_lock_init(&tgcred->lock);
  	new->tgcred = tgcred;
  #endif
  
  #ifdef CONFIG_SECURITY
  	new->security = NULL;
  #endif
  	if (security_prepare_creds(new, &init_cred, GFP_ATOMIC) < 0)
  		goto error;
  
  	BUG_ON(atomic_read(&new->usage) != 1);
  	return new;
  
  error:
  	put_cred(new);
  	return NULL;
  }
f1752eec6   David Howells   CRED: Detach the ...
258
259
  /*
   * Copy credentials for the new process created by fork()
d84f4f992   David Howells   CRED: Inaugurate ...
260
261
262
   *
   * We share if we can, but under some circumstances we have to generate a new
   * set.
3b11a1dec   David Howells   CRED: Differentia...
263
264
265
   *
   * The new process gets the current process's subjective credentials as its
   * objective and subjective credentials
f1752eec6   David Howells   CRED: Detach the ...
266
267
268
   */
  int copy_creds(struct task_struct *p, unsigned long clone_flags)
  {
d84f4f992   David Howells   CRED: Inaugurate ...
269
270
271
272
  #ifdef CONFIG_KEYS
  	struct thread_group_cred *tgcred;
  #endif
  	struct cred *new;
18b6e0414   Serge Hallyn   User namespaces: ...
273
  	int ret;
d84f4f992   David Howells   CRED: Inaugurate ...
274
275
  
  	mutex_init(&p->cred_exec_mutex);
f1752eec6   David Howells   CRED: Detach the ...
276

d84f4f992   David Howells   CRED: Inaugurate ...
277
278
279
280
281
282
  	if (
  #ifdef CONFIG_KEYS
  		!p->cred->thread_keyring &&
  #endif
  		clone_flags & CLONE_THREAD
  	    ) {
3b11a1dec   David Howells   CRED: Differentia...
283
  		p->real_cred = get_cred(p->cred);
d84f4f992   David Howells   CRED: Inaugurate ...
284
285
286
287
288
289
290
  		get_cred(p->cred);
  		atomic_inc(&p->cred->user->processes);
  		return 0;
  	}
  
  	new = prepare_creds();
  	if (!new)
f1752eec6   David Howells   CRED: Detach the ...
291
  		return -ENOMEM;
18b6e0414   Serge Hallyn   User namespaces: ...
292
293
294
295
296
  	if (clone_flags & CLONE_NEWUSER) {
  		ret = create_user_ns(new);
  		if (ret < 0)
  			goto error_put;
  	}
bb952bb98   David Howells   CRED: Separate pe...
297
  #ifdef CONFIG_KEYS
d84f4f992   David Howells   CRED: Inaugurate ...
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
  	/* new threads get their own thread keyrings if their parent already
  	 * had one */
  	if (new->thread_keyring) {
  		key_put(new->thread_keyring);
  		new->thread_keyring = NULL;
  		if (clone_flags & CLONE_THREAD)
  			install_thread_keyring_to_cred(new);
  	}
  
  	/* we share the process and session keyrings between all the threads in
  	 * a process - this is slightly icky as we violate COW credentials a
  	 * bit */
  	if (!(clone_flags & CLONE_THREAD)) {
  		tgcred = kmalloc(sizeof(*tgcred), GFP_KERNEL);
  		if (!tgcred) {
18b6e0414   Serge Hallyn   User namespaces: ...
313
314
  			ret = -ENOMEM;
  			goto error_put;
bb952bb98   David Howells   CRED: Separate pe...
315
  		}
d84f4f992   David Howells   CRED: Inaugurate ...
316
317
318
319
320
321
322
  		atomic_set(&tgcred->usage, 1);
  		spin_lock_init(&tgcred->lock);
  		tgcred->process_keyring = NULL;
  		tgcred->session_keyring = key_get(new->tgcred->session_keyring);
  
  		release_tgcred(new);
  		new->tgcred = tgcred;
bb952bb98   David Howells   CRED: Separate pe...
323
324
  	}
  #endif
d84f4f992   David Howells   CRED: Inaugurate ...
325
  	atomic_inc(&new->user->processes);
3b11a1dec   David Howells   CRED: Differentia...
326
  	p->cred = p->real_cred = get_cred(new);
d84f4f992   David Howells   CRED: Inaugurate ...
327
  	return 0;
18b6e0414   Serge Hallyn   User namespaces: ...
328
329
330
331
  
  error_put:
  	put_cred(new);
  	return ret;
d84f4f992   David Howells   CRED: Inaugurate ...
332
  }
f1752eec6   David Howells   CRED: Detach the ...
333

d84f4f992   David Howells   CRED: Inaugurate ...
334
335
336
337
338
  /**
   * commit_creds - Install new credentials upon the current task
   * @new: The credentials to be assigned
   *
   * Install a new set of credentials to the current task, using RCU to replace
3b11a1dec   David Howells   CRED: Differentia...
339
340
341
   * the old set.  Both the objective and the subjective credentials pointers are
   * updated.  This function may not be called if the subjective credentials are
   * in an overridden state.
d84f4f992   David Howells   CRED: Inaugurate ...
342
343
344
345
346
347
348
349
350
351
   *
   * This function eats the caller's reference to the new credentials.
   *
   * Always returns 0 thus allowing this function to be tail-called at the end
   * of, say, sys_setgid().
   */
  int commit_creds(struct cred *new)
  {
  	struct task_struct *task = current;
  	const struct cred *old;
3b11a1dec   David Howells   CRED: Differentia...
352
353
  	BUG_ON(task->cred != task->real_cred);
  	BUG_ON(atomic_read(&task->real_cred->usage) < 2);
d84f4f992   David Howells   CRED: Inaugurate ...
354
  	BUG_ON(atomic_read(&new->usage) < 1);
d84f4f992   David Howells   CRED: Inaugurate ...
355

3b11a1dec   David Howells   CRED: Differentia...
356
  	old = task->real_cred;
d84f4f992   David Howells   CRED: Inaugurate ...
357
  	security_commit_creds(new, old);
3b11a1dec   David Howells   CRED: Differentia...
358
  	get_cred(new); /* we will require a ref for the subj creds too */
d84f4f992   David Howells   CRED: Inaugurate ...
359
360
361
362
363
364
365
366
367
  	/* dumpability changes */
  	if (old->euid != new->euid ||
  	    old->egid != new->egid ||
  	    old->fsuid != new->fsuid ||
  	    old->fsgid != new->fsgid ||
  	    !cap_issubset(new->cap_permitted, old->cap_permitted)) {
  		set_dumpable(task->mm, suid_dumpable);
  		task->pdeath_signal = 0;
  		smp_wmb();
f1752eec6   David Howells   CRED: Detach the ...
368
  	}
d84f4f992   David Howells   CRED: Inaugurate ...
369
370
371
372
373
374
375
376
377
378
379
380
381
382
  	/* alter the thread keyring */
  	if (new->fsuid != old->fsuid)
  		key_fsuid_changed(task);
  	if (new->fsgid != old->fsgid)
  		key_fsgid_changed(task);
  
  	/* do it
  	 * - What if a process setreuid()'s and this brings the
  	 *   new uid over his NPROC rlimit?  We can check this now
  	 *   cheaply with the new uid cache, so if it matters
  	 *   we should be checking for it.  -DaveM
  	 */
  	if (new->user != old->user)
  		atomic_inc(&new->user->processes);
3b11a1dec   David Howells   CRED: Differentia...
383
  	rcu_assign_pointer(task->real_cred, new);
d84f4f992   David Howells   CRED: Inaugurate ...
384
385
386
387
388
389
390
391
392
393
394
395
  	rcu_assign_pointer(task->cred, new);
  	if (new->user != old->user)
  		atomic_dec(&old->user->processes);
  
  	sched_switch_user(task);
  
  	/* send notifications */
  	if (new->uid   != old->uid  ||
  	    new->euid  != old->euid ||
  	    new->suid  != old->suid ||
  	    new->fsuid != old->fsuid)
  		proc_id_connector(task, PROC_EVENT_UID);
f1752eec6   David Howells   CRED: Detach the ...
396

d84f4f992   David Howells   CRED: Inaugurate ...
397
398
399
400
401
  	if (new->gid   != old->gid  ||
  	    new->egid  != old->egid ||
  	    new->sgid  != old->sgid ||
  	    new->fsgid != old->fsgid)
  		proc_id_connector(task, PROC_EVENT_GID);
f1752eec6   David Howells   CRED: Detach the ...
402

3b11a1dec   David Howells   CRED: Differentia...
403
404
  	/* release the old obj and subj refs both */
  	put_cred(old);
d84f4f992   David Howells   CRED: Inaugurate ...
405
  	put_cred(old);
f1752eec6   David Howells   CRED: Detach the ...
406
407
  	return 0;
  }
d84f4f992   David Howells   CRED: Inaugurate ...
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
  EXPORT_SYMBOL(commit_creds);
  
  /**
   * abort_creds - Discard a set of credentials and unlock the current task
   * @new: The credentials that were going to be applied
   *
   * Discard a set of credentials that were under construction and unlock the
   * current task.
   */
  void abort_creds(struct cred *new)
  {
  	BUG_ON(atomic_read(&new->usage) < 1);
  	put_cred(new);
  }
  EXPORT_SYMBOL(abort_creds);
  
  /**
3b11a1dec   David Howells   CRED: Differentia...
425
   * override_creds - Override the current process's subjective credentials
d84f4f992   David Howells   CRED: Inaugurate ...
426
427
   * @new: The credentials to be assigned
   *
3b11a1dec   David Howells   CRED: Differentia...
428
429
   * Install a set of temporary override subjective credentials on the current
   * process, returning the old set for later reversion.
d84f4f992   David Howells   CRED: Inaugurate ...
430
431
432
433
434
435
436
437
438
439
440
   */
  const struct cred *override_creds(const struct cred *new)
  {
  	const struct cred *old = current->cred;
  
  	rcu_assign_pointer(current->cred, get_cred(new));
  	return old;
  }
  EXPORT_SYMBOL(override_creds);
  
  /**
3b11a1dec   David Howells   CRED: Differentia...
441
   * revert_creds - Revert a temporary subjective credentials override
d84f4f992   David Howells   CRED: Inaugurate ...
442
443
   * @old: The credentials to be restored
   *
3b11a1dec   David Howells   CRED: Differentia...
444
445
   * Revert a temporary set of override subjective credentials to an old set,
   * discarding the override set.
d84f4f992   David Howells   CRED: Inaugurate ...
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
   */
  void revert_creds(const struct cred *old)
  {
  	const struct cred *override = current->cred;
  
  	rcu_assign_pointer(current->cred, old);
  	put_cred(override);
  }
  EXPORT_SYMBOL(revert_creds);
  
  /*
   * initialise the credentials stuff
   */
  void __init cred_init(void)
  {
  	/* allocate a slab in which we can store credentials */
  	cred_jar = kmem_cache_create("cred_jar", sizeof(struct cred),
  				     0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
  }
3a3b7ce93   David Howells   CRED: Allow kerne...
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
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
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
  
  /**
   * prepare_kernel_cred - Prepare a set of credentials for a kernel service
   * @daemon: A userspace daemon to be used as a reference
   *
   * Prepare a set of credentials for a kernel service.  This can then be used to
   * override a task's own credentials so that work can be done on behalf of that
   * task that requires a different subjective context.
   *
   * @daemon is used to provide a base for the security record, but can be NULL.
   * If @daemon is supplied, then the security data will be derived from that;
   * otherwise they'll be set to 0 and no groups, full capabilities and no keys.
   *
   * The caller may change these controls afterwards if desired.
   *
   * Returns the new credentials or NULL if out of memory.
   *
   * Does not take, and does not return holding current->cred_replace_mutex.
   */
  struct cred *prepare_kernel_cred(struct task_struct *daemon)
  {
  	const struct cred *old;
  	struct cred *new;
  
  	new = kmem_cache_alloc(cred_jar, GFP_KERNEL);
  	if (!new)
  		return NULL;
  
  	if (daemon)
  		old = get_task_cred(daemon);
  	else
  		old = get_cred(&init_cred);
  
  	get_uid(new->user);
  	get_group_info(new->group_info);
  
  #ifdef CONFIG_KEYS
  	atomic_inc(&init_tgcred.usage);
  	new->tgcred = &init_tgcred;
  	new->request_key_auth = NULL;
  	new->thread_keyring = NULL;
  	new->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
  #endif
  
  #ifdef CONFIG_SECURITY
  	new->security = NULL;
  #endif
  	if (security_prepare_creds(new, old, GFP_KERNEL) < 0)
  		goto error;
  
  	atomic_set(&new->usage, 1);
  	put_cred(old);
  	return new;
  
  error:
  	put_cred(new);
  	return NULL;
  }
  EXPORT_SYMBOL(prepare_kernel_cred);
  
  /**
   * set_security_override - Set the security ID in a set of credentials
   * @new: The credentials to alter
   * @secid: The LSM security ID to set
   *
   * Set the LSM security ID in a set of credentials so that the subjective
   * security is overridden when an alternative set of credentials is used.
   */
  int set_security_override(struct cred *new, u32 secid)
  {
  	return security_kernel_act_as(new, secid);
  }
  EXPORT_SYMBOL(set_security_override);
  
  /**
   * set_security_override_from_ctx - Set the security ID in a set of credentials
   * @new: The credentials to alter
   * @secctx: The LSM security context to generate the security ID from.
   *
   * Set the LSM security ID in a set of credentials so that the subjective
   * security is overridden when an alternative set of credentials is used.  The
   * security ID is specified in string form as a security context to be
   * interpreted by the LSM.
   */
  int set_security_override_from_ctx(struct cred *new, const char *secctx)
  {
  	u32 secid;
  	int ret;
  
  	ret = security_secctx_to_secid(secctx, strlen(secctx), &secid);
  	if (ret < 0)
  		return ret;
  
  	return set_security_override(new, secid);
  }
  EXPORT_SYMBOL(set_security_override_from_ctx);
  
  /**
   * set_create_files_as - Set the LSM file create context in a set of credentials
   * @new: The credentials to alter
   * @inode: The inode to take the context from
   *
   * Change the LSM file creation context in a set of credentials to be the same
   * as the object context of the specified inode, so that the new inodes have
   * the same MAC context as that inode.
   */
  int set_create_files_as(struct cred *new, struct inode *inode)
  {
  	new->fsuid = inode->i_uid;
  	new->fsgid = inode->i_gid;
  	return security_kernel_create_files_as(new, inode);
  }
  EXPORT_SYMBOL(set_create_files_as);