domain.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827
  1. /*
  2. * AppArmor security module
  3. *
  4. * This file contains AppArmor policy attachment and domain transitions
  5. *
  6. * Copyright (C) 2002-2008 Novell/SUSE
  7. * Copyright 2009-2010 Canonical Ltd.
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public License as
  11. * published by the Free Software Foundation, version 2 of the
  12. * License.
  13. */
  14. #include <linux/errno.h>
  15. #include <linux/fdtable.h>
  16. #include <linux/file.h>
  17. #include <linux/mount.h>
  18. #include <linux/syscalls.h>
  19. #include <linux/tracehook.h>
  20. #include <linux/personality.h>
  21. #include "include/audit.h"
  22. #include "include/apparmorfs.h"
  23. #include "include/context.h"
  24. #include "include/domain.h"
  25. #include "include/file.h"
  26. #include "include/ipc.h"
  27. #include "include/match.h"
  28. #include "include/path.h"
  29. #include "include/policy.h"
  30. /**
  31. * aa_free_domain_entries - free entries in a domain table
  32. * @domain: the domain table to free (MAYBE NULL)
  33. */
  34. void aa_free_domain_entries(struct aa_domain *domain)
  35. {
  36. int i;
  37. if (domain) {
  38. if (!domain->table)
  39. return;
  40. for (i = 0; i < domain->size; i++)
  41. kzfree(domain->table[i]);
  42. kzfree(domain->table);
  43. domain->table = NULL;
  44. }
  45. }
  46. /**
  47. * may_change_ptraced_domain - check if can change profile on ptraced task
  48. * @task: task we want to change profile of (NOT NULL)
  49. * @to_profile: profile to change to (NOT NULL)
  50. *
  51. * Check if the task is ptraced and if so if the tracing task is allowed
  52. * to trace the new domain
  53. *
  54. * Returns: %0 or error if change not allowed
  55. */
  56. static int may_change_ptraced_domain(struct task_struct *task,
  57. struct aa_profile *to_profile)
  58. {
  59. struct task_struct *tracer;
  60. const struct cred *cred = NULL;
  61. struct aa_profile *tracerp = NULL;
  62. int error = 0;
  63. rcu_read_lock();
  64. tracer = ptrace_parent(task);
  65. if (tracer) {
  66. /* released below */
  67. cred = get_task_cred(tracer);
  68. tracerp = aa_cred_profile(cred);
  69. }
  70. /* not ptraced */
  71. if (!tracer || unconfined(tracerp))
  72. goto out;
  73. error = aa_may_ptrace(tracer, tracerp, to_profile, PTRACE_MODE_ATTACH);
  74. out:
  75. rcu_read_unlock();
  76. if (cred)
  77. put_cred(cred);
  78. return error;
  79. }
  80. /**
  81. * change_profile_perms - find permissions for change_profile
  82. * @profile: the current profile (NOT NULL)
  83. * @ns: the namespace being switched to (NOT NULL)
  84. * @name: the name of the profile to change to (NOT NULL)
  85. * @request: requested perms
  86. * @start: state to start matching in
  87. *
  88. * Returns: permission set
  89. */
  90. static struct file_perms change_profile_perms(struct aa_profile *profile,
  91. struct aa_namespace *ns,
  92. const char *name, u32 request,
  93. unsigned int start)
  94. {
  95. struct file_perms perms;
  96. struct path_cond cond = { };
  97. unsigned int state;
  98. if (unconfined(profile)) {
  99. perms.allow = AA_MAY_CHANGE_PROFILE | AA_MAY_ONEXEC;
  100. perms.audit = perms.quiet = perms.kill = 0;
  101. return perms;
  102. } else if (!profile->file.dfa) {
  103. return nullperms;
  104. } else if ((ns == profile->ns)) {
  105. /* try matching against rules with out namespace prepended */
  106. aa_str_perms(profile->file.dfa, start, name, &cond, &perms);
  107. if (COMBINED_PERM_MASK(perms) & request)
  108. return perms;
  109. }
  110. /* try matching with namespace name and then profile */
  111. state = aa_dfa_match(profile->file.dfa, start, ns->base.name);
  112. state = aa_dfa_match_len(profile->file.dfa, state, ":", 1);
  113. aa_str_perms(profile->file.dfa, state, name, &cond, &perms);
  114. return perms;
  115. }
  116. /**
  117. * __attach_match_ - find an attachment match
  118. * @name - to match against (NOT NULL)
  119. * @head - profile list to walk (NOT NULL)
  120. *
  121. * Do a linear search on the profiles in the list. There is a matching
  122. * preference where an exact match is preferred over a name which uses
  123. * expressions to match, and matching expressions with the greatest
  124. * xmatch_len are preferred.
  125. *
  126. * Requires: @head not be shared or have appropriate locks held
  127. *
  128. * Returns: profile or NULL if no match found
  129. */
  130. static struct aa_profile *__attach_match(const char *name,
  131. struct list_head *head)
  132. {
  133. int len = 0;
  134. struct aa_profile *profile, *candidate = NULL;
  135. list_for_each_entry(profile, head, base.list) {
  136. if (profile->flags & PFLAG_NULL)
  137. continue;
  138. if (profile->xmatch && profile->xmatch_len > len) {
  139. unsigned int state = aa_dfa_match(profile->xmatch,
  140. DFA_START, name);
  141. u32 perm = dfa_user_allow(profile->xmatch, state);
  142. /* any accepting state means a valid match. */
  143. if (perm & MAY_EXEC) {
  144. candidate = profile;
  145. len = profile->xmatch_len;
  146. }
  147. } else if (!strcmp(profile->base.name, name))
  148. /* exact non-re match, no more searching required */
  149. return profile;
  150. }
  151. return candidate;
  152. }
  153. /**
  154. * find_attach - do attachment search for unconfined processes
  155. * @ns: the current namespace (NOT NULL)
  156. * @list: list to search (NOT NULL)
  157. * @name: the executable name to match against (NOT NULL)
  158. *
  159. * Returns: profile or NULL if no match found
  160. */
  161. static struct aa_profile *find_attach(struct aa_namespace *ns,
  162. struct list_head *list, const char *name)
  163. {
  164. struct aa_profile *profile;
  165. read_lock(&ns->lock);
  166. profile = aa_get_profile(__attach_match(name, list));
  167. read_unlock(&ns->lock);
  168. return profile;
  169. }
  170. /**
  171. * separate_fqname - separate the namespace and profile names
  172. * @fqname: the fqname name to split (NOT NULL)
  173. * @ns_name: the namespace name if it exists (NOT NULL)
  174. *
  175. * This is the xtable equivalent routine of aa_split_fqname. It finds the
  176. * split in an xtable fqname which contains an embedded \0 instead of a :
  177. * if a namespace is specified. This is done so the xtable is constant and
  178. * isn't re-split on every lookup.
  179. *
  180. * Either the profile or namespace name may be optional but if the namespace
  181. * is specified the profile name termination must be present. This results
  182. * in the following possible encodings:
  183. * profile_name\0
  184. * :ns_name\0profile_name\0
  185. * :ns_name\0\0
  186. *
  187. * NOTE: the xtable fqname is pre-validated at load time in unpack_trans_table
  188. *
  189. * Returns: profile name if it is specified else NULL
  190. */
  191. static const char *separate_fqname(const char *fqname, const char **ns_name)
  192. {
  193. const char *name;
  194. if (fqname[0] == ':') {
  195. /* In this case there is guaranteed to be two \0 terminators
  196. * in the string. They are verified at load time by
  197. * by unpack_trans_table
  198. */
  199. *ns_name = fqname + 1; /* skip : */
  200. name = *ns_name + strlen(*ns_name) + 1;
  201. if (!*name)
  202. name = NULL;
  203. } else {
  204. *ns_name = NULL;
  205. name = fqname;
  206. }
  207. return name;
  208. }
  209. static const char *next_name(int xtype, const char *name)
  210. {
  211. return NULL;
  212. }
  213. /**
  214. * x_table_lookup - lookup an x transition name via transition table
  215. * @profile: current profile (NOT NULL)
  216. * @xindex: index into x transition table
  217. *
  218. * Returns: refcounted profile, or NULL on failure (MAYBE NULL)
  219. */
  220. static struct aa_profile *x_table_lookup(struct aa_profile *profile, u32 xindex)
  221. {
  222. struct aa_profile *new_profile = NULL;
  223. struct aa_namespace *ns = profile->ns;
  224. u32 xtype = xindex & AA_X_TYPE_MASK;
  225. int index = xindex & AA_X_INDEX_MASK;
  226. const char *name;
  227. /* index is guaranteed to be in range, validated at load time */
  228. for (name = profile->file.trans.table[index]; !new_profile && name;
  229. name = next_name(xtype, name)) {
  230. struct aa_namespace *new_ns;
  231. const char *xname = NULL;
  232. new_ns = NULL;
  233. if (xindex & AA_X_CHILD) {
  234. /* release by caller */
  235. new_profile = aa_find_child(profile, name);
  236. continue;
  237. } else if (*name == ':') {
  238. /* switching namespace */
  239. const char *ns_name;
  240. xname = name = separate_fqname(name, &ns_name);
  241. if (!xname)
  242. /* no name so use profile name */
  243. xname = profile->base.hname;
  244. if (*ns_name == '@') {
  245. /* TODO: variable support */
  246. ;
  247. }
  248. /* released below */
  249. new_ns = aa_find_namespace(ns, ns_name);
  250. if (!new_ns)
  251. continue;
  252. } else if (*name == '@') {
  253. /* TODO: variable support */
  254. continue;
  255. } else {
  256. /* basic namespace lookup */
  257. xname = name;
  258. }
  259. /* released by caller */
  260. new_profile = aa_lookup_profile(new_ns ? new_ns : ns, xname);
  261. aa_put_namespace(new_ns);
  262. }
  263. /* released by caller */
  264. return new_profile;
  265. }
  266. /**
  267. * x_to_profile - get target profile for a given xindex
  268. * @profile: current profile (NOT NULL)
  269. * @name: name to lookup (NOT NULL)
  270. * @xindex: index into x transition table
  271. *
  272. * find profile for a transition index
  273. *
  274. * Returns: refcounted profile or NULL if not found available
  275. */
  276. static struct aa_profile *x_to_profile(struct aa_profile *profile,
  277. const char *name, u32 xindex)
  278. {
  279. struct aa_profile *new_profile = NULL;
  280. struct aa_namespace *ns = profile->ns;
  281. u32 xtype = xindex & AA_X_TYPE_MASK;
  282. switch (xtype) {
  283. case AA_X_NONE:
  284. /* fail exec unless ix || ux fallback - handled by caller */
  285. return NULL;
  286. case AA_X_NAME:
  287. if (xindex & AA_X_CHILD)
  288. /* released by caller */
  289. new_profile = find_attach(ns, &profile->base.profiles,
  290. name);
  291. else
  292. /* released by caller */
  293. new_profile = find_attach(ns, &ns->base.profiles,
  294. name);
  295. break;
  296. case AA_X_TABLE:
  297. /* released by caller */
  298. new_profile = x_table_lookup(profile, xindex);
  299. break;
  300. }
  301. /* released by caller */
  302. return new_profile;
  303. }
  304. /**
  305. * apparmor_bprm_set_creds - set the new creds on the bprm struct
  306. * @bprm: binprm for the exec (NOT NULL)
  307. *
  308. * Returns: %0 or error on failure
  309. */
  310. int apparmor_bprm_set_creds(struct linux_binprm *bprm)
  311. {
  312. struct aa_task_cxt *cxt;
  313. struct aa_profile *profile, *new_profile = NULL;
  314. struct aa_namespace *ns;
  315. char *buffer = NULL;
  316. unsigned int state;
  317. struct file_perms perms = {};
  318. struct path_cond cond = {
  319. bprm->file->f_path.dentry->d_inode->i_uid,
  320. bprm->file->f_path.dentry->d_inode->i_mode
  321. };
  322. const char *name = NULL, *target = NULL, *info = NULL;
  323. int error = cap_bprm_set_creds(bprm);
  324. if (error)
  325. return error;
  326. if (bprm->cred_prepared)
  327. return 0;
  328. /* XXX: no_new_privs is not usable with AppArmor yet */
  329. if (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS)
  330. return -EPERM;
  331. cxt = bprm->cred->security;
  332. BUG_ON(!cxt);
  333. profile = aa_get_profile(aa_newest_version(cxt->profile));
  334. /*
  335. * get the namespace from the replacement profile as replacement
  336. * can change the namespace
  337. */
  338. ns = profile->ns;
  339. state = profile->file.start;
  340. /* buffer freed below, name is pointer into buffer */
  341. error = aa_path_name(&bprm->file->f_path, profile->path_flags, &buffer,
  342. &name, &info);
  343. if (error) {
  344. if (profile->flags &
  345. (PFLAG_IX_ON_NAME_ERROR | PFLAG_UNCONFINED))
  346. error = 0;
  347. name = bprm->filename;
  348. goto audit;
  349. }
  350. /* Test for onexec first as onexec directives override other
  351. * x transitions.
  352. */
  353. if (unconfined(profile)) {
  354. /* unconfined task */
  355. if (cxt->onexec)
  356. /* change_profile on exec already been granted */
  357. new_profile = aa_get_profile(cxt->onexec);
  358. else
  359. new_profile = find_attach(ns, &ns->base.profiles, name);
  360. if (!new_profile)
  361. goto cleanup;
  362. goto apply;
  363. }
  364. /* find exec permissions for name */
  365. state = aa_str_perms(profile->file.dfa, state, name, &cond, &perms);
  366. if (cxt->onexec) {
  367. struct file_perms cp;
  368. info = "change_profile onexec";
  369. if (!(perms.allow & AA_MAY_ONEXEC))
  370. goto audit;
  371. /* test if this exec can be paired with change_profile onexec.
  372. * onexec permission is linked to exec with a standard pairing
  373. * exec\0change_profile
  374. */
  375. state = aa_dfa_null_transition(profile->file.dfa, state);
  376. cp = change_profile_perms(profile, cxt->onexec->ns,
  377. cxt->onexec->base.name,
  378. AA_MAY_ONEXEC, state);
  379. if (!(cp.allow & AA_MAY_ONEXEC))
  380. goto audit;
  381. new_profile = aa_get_profile(aa_newest_version(cxt->onexec));
  382. goto apply;
  383. }
  384. if (perms.allow & MAY_EXEC) {
  385. /* exec permission determine how to transition */
  386. new_profile = x_to_profile(profile, name, perms.xindex);
  387. if (!new_profile) {
  388. if (perms.xindex & AA_X_INHERIT) {
  389. /* (p|c|n)ix - don't change profile but do
  390. * use the newest version, which was picked
  391. * up above when getting profile
  392. */
  393. info = "ix fallback";
  394. new_profile = aa_get_profile(profile);
  395. goto x_clear;
  396. } else if (perms.xindex & AA_X_UNCONFINED) {
  397. new_profile = aa_get_profile(ns->unconfined);
  398. info = "ux fallback";
  399. } else {
  400. error = -ENOENT;
  401. info = "profile not found";
  402. }
  403. }
  404. } else if (COMPLAIN_MODE(profile)) {
  405. /* no exec permission - are we in learning mode */
  406. new_profile = aa_new_null_profile(profile, 0);
  407. if (!new_profile) {
  408. error = -ENOMEM;
  409. info = "could not create null profile";
  410. } else {
  411. error = -EACCES;
  412. target = new_profile->base.hname;
  413. }
  414. perms.xindex |= AA_X_UNSAFE;
  415. } else
  416. /* fail exec */
  417. error = -EACCES;
  418. if (!new_profile)
  419. goto audit;
  420. if (bprm->unsafe & LSM_UNSAFE_SHARE) {
  421. /* FIXME: currently don't mediate shared state */
  422. ;
  423. }
  424. if (bprm->unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
  425. error = may_change_ptraced_domain(current, new_profile);
  426. if (error) {
  427. aa_put_profile(new_profile);
  428. goto audit;
  429. }
  430. }
  431. /* Determine if secure exec is needed.
  432. * Can be at this point for the following reasons:
  433. * 1. unconfined switching to confined
  434. * 2. confined switching to different confinement
  435. * 3. confined switching to unconfined
  436. *
  437. * Cases 2 and 3 are marked as requiring secure exec
  438. * (unless policy specified "unsafe exec")
  439. *
  440. * bprm->unsafe is used to cache the AA_X_UNSAFE permission
  441. * to avoid having to recompute in secureexec
  442. */
  443. if (!(perms.xindex & AA_X_UNSAFE)) {
  444. AA_DEBUG("scrubbing environment variables for %s profile=%s\n",
  445. name, new_profile->base.hname);
  446. bprm->unsafe |= AA_SECURE_X_NEEDED;
  447. }
  448. apply:
  449. target = new_profile->base.hname;
  450. /* when transitioning profiles clear unsafe personality bits */
  451. bprm->per_clear |= PER_CLEAR_ON_SETID;
  452. x_clear:
  453. aa_put_profile(cxt->profile);
  454. /* transfer new profile reference will be released when cxt is freed */
  455. cxt->profile = new_profile;
  456. /* clear out all temporary/transitional state from the context */
  457. aa_put_profile(cxt->previous);
  458. aa_put_profile(cxt->onexec);
  459. cxt->previous = NULL;
  460. cxt->onexec = NULL;
  461. cxt->token = 0;
  462. audit:
  463. error = aa_audit_file(profile, &perms, GFP_KERNEL, OP_EXEC, MAY_EXEC,
  464. name, target, cond.uid, info, error);
  465. cleanup:
  466. aa_put_profile(profile);
  467. kfree(buffer);
  468. return error;
  469. }
  470. /**
  471. * apparmor_bprm_secureexec - determine if secureexec is needed
  472. * @bprm: binprm for exec (NOT NULL)
  473. *
  474. * Returns: %1 if secureexec is needed else %0
  475. */
  476. int apparmor_bprm_secureexec(struct linux_binprm *bprm)
  477. {
  478. int ret = cap_bprm_secureexec(bprm);
  479. /* the decision to use secure exec is computed in set_creds
  480. * and stored in bprm->unsafe.
  481. */
  482. if (!ret && (bprm->unsafe & AA_SECURE_X_NEEDED))
  483. ret = 1;
  484. return ret;
  485. }
  486. /**
  487. * apparmor_bprm_committing_creds - do task cleanup on committing new creds
  488. * @bprm: binprm for the exec (NOT NULL)
  489. */
  490. void apparmor_bprm_committing_creds(struct linux_binprm *bprm)
  491. {
  492. struct aa_profile *profile = __aa_current_profile();
  493. struct aa_task_cxt *new_cxt = bprm->cred->security;
  494. /* bail out if unconfined or not changing profile */
  495. if ((new_cxt->profile == profile) ||
  496. (unconfined(new_cxt->profile)))
  497. return;
  498. current->pdeath_signal = 0;
  499. /* reset soft limits and set hard limits for the new profile */
  500. __aa_transition_rlimits(profile, new_cxt->profile);
  501. }
  502. /**
  503. * apparmor_bprm_commited_cred - do cleanup after new creds committed
  504. * @bprm: binprm for the exec (NOT NULL)
  505. */
  506. void apparmor_bprm_committed_creds(struct linux_binprm *bprm)
  507. {
  508. /* TODO: cleanup signals - ipc mediation */
  509. return;
  510. }
  511. /*
  512. * Functions for self directed profile change
  513. */
  514. /**
  515. * new_compound_name - create an hname with @n2 appended to @n1
  516. * @n1: base of hname (NOT NULL)
  517. * @n2: name to append (NOT NULL)
  518. *
  519. * Returns: new name or NULL on error
  520. */
  521. static char *new_compound_name(const char *n1, const char *n2)
  522. {
  523. char *name = kmalloc(strlen(n1) + strlen(n2) + 3, GFP_KERNEL);
  524. if (name)
  525. sprintf(name, "%s//%s", n1, n2);
  526. return name;
  527. }
  528. /**
  529. * aa_change_hat - change hat to/from subprofile
  530. * @hats: vector of hat names to try changing into (MAYBE NULL if @count == 0)
  531. * @count: number of hat names in @hats
  532. * @token: magic value to validate the hat change
  533. * @permtest: true if this is just a permission test
  534. *
  535. * Change to the first profile specified in @hats that exists, and store
  536. * the @hat_magic in the current task context. If the count == 0 and the
  537. * @token matches that stored in the current task context, return to the
  538. * top level profile.
  539. *
  540. * Returns %0 on success, error otherwise.
  541. */
  542. int aa_change_hat(const char *hats[], int count, u64 token, bool permtest)
  543. {
  544. const struct cred *cred;
  545. struct aa_task_cxt *cxt;
  546. struct aa_profile *profile, *previous_profile, *hat = NULL;
  547. char *name = NULL;
  548. int i;
  549. struct file_perms perms = {};
  550. const char *target = NULL, *info = NULL;
  551. int error = 0;
  552. /* released below */
  553. cred = get_current_cred();
  554. cxt = cred->security;
  555. profile = aa_cred_profile(cred);
  556. previous_profile = cxt->previous;
  557. if (unconfined(profile)) {
  558. info = "unconfined";
  559. error = -EPERM;
  560. goto audit;
  561. }
  562. if (count) {
  563. /* attempting to change into a new hat or switch to a sibling */
  564. struct aa_profile *root;
  565. root = PROFILE_IS_HAT(profile) ? profile->parent : profile;
  566. /* find first matching hat */
  567. for (i = 0; i < count && !hat; i++)
  568. /* released below */
  569. hat = aa_find_child(root, hats[i]);
  570. if (!hat) {
  571. if (!COMPLAIN_MODE(root) || permtest) {
  572. if (list_empty(&root->base.profiles))
  573. error = -ECHILD;
  574. else
  575. error = -ENOENT;
  576. goto out;
  577. }
  578. /*
  579. * In complain mode and failed to match any hats.
  580. * Audit the failure is based off of the first hat
  581. * supplied. This is done due how userspace
  582. * interacts with change_hat.
  583. *
  584. * TODO: Add logging of all failed hats
  585. */
  586. /* freed below */
  587. name = new_compound_name(root->base.hname, hats[0]);
  588. target = name;
  589. /* released below */
  590. hat = aa_new_null_profile(profile, 1);
  591. if (!hat) {
  592. info = "failed null profile create";
  593. error = -ENOMEM;
  594. goto audit;
  595. }
  596. } else {
  597. target = hat->base.hname;
  598. if (!PROFILE_IS_HAT(hat)) {
  599. info = "target not hat";
  600. error = -EPERM;
  601. goto audit;
  602. }
  603. }
  604. error = may_change_ptraced_domain(current, hat);
  605. if (error) {
  606. info = "ptraced";
  607. error = -EPERM;
  608. goto audit;
  609. }
  610. if (!permtest) {
  611. error = aa_set_current_hat(hat, token);
  612. if (error == -EACCES)
  613. /* kill task in case of brute force attacks */
  614. perms.kill = AA_MAY_CHANGEHAT;
  615. else if (name && !error)
  616. /* reset error for learning of new hats */
  617. error = -ENOENT;
  618. }
  619. } else if (previous_profile) {
  620. /* Return to saved profile. Kill task if restore fails
  621. * to avoid brute force attacks
  622. */
  623. target = previous_profile->base.hname;
  624. error = aa_restore_previous_profile(token);
  625. perms.kill = AA_MAY_CHANGEHAT;
  626. } else
  627. /* ignore restores when there is no saved profile */
  628. goto out;
  629. audit:
  630. if (!permtest)
  631. error = aa_audit_file(profile, &perms, GFP_KERNEL,
  632. OP_CHANGE_HAT, AA_MAY_CHANGEHAT, NULL,
  633. target, 0, info, error);
  634. out:
  635. aa_put_profile(hat);
  636. kfree(name);
  637. put_cred(cred);
  638. return error;
  639. }
  640. /**
  641. * aa_change_profile - perform a one-way profile transition
  642. * @ns_name: name of the profile namespace to change to (MAYBE NULL)
  643. * @hname: name of profile to change to (MAYBE NULL)
  644. * @onexec: whether this transition is to take place immediately or at exec
  645. * @permtest: true if this is just a permission test
  646. *
  647. * Change to new profile @name. Unlike with hats, there is no way
  648. * to change back. If @name isn't specified the current profile name is
  649. * used.
  650. * If @onexec then the transition is delayed until
  651. * the next exec.
  652. *
  653. * Returns %0 on success, error otherwise.
  654. */
  655. int aa_change_profile(const char *ns_name, const char *hname, bool onexec,
  656. bool permtest)
  657. {
  658. const struct cred *cred;
  659. struct aa_task_cxt *cxt;
  660. struct aa_profile *profile, *target = NULL;
  661. struct aa_namespace *ns = NULL;
  662. struct file_perms perms = {};
  663. const char *name = NULL, *info = NULL;
  664. int op, error = 0;
  665. u32 request;
  666. if (!hname && !ns_name)
  667. return -EINVAL;
  668. if (onexec) {
  669. request = AA_MAY_ONEXEC;
  670. op = OP_CHANGE_ONEXEC;
  671. } else {
  672. request = AA_MAY_CHANGE_PROFILE;
  673. op = OP_CHANGE_PROFILE;
  674. }
  675. cred = get_current_cred();
  676. cxt = cred->security;
  677. profile = aa_cred_profile(cred);
  678. if (ns_name) {
  679. /* released below */
  680. ns = aa_find_namespace(profile->ns, ns_name);
  681. if (!ns) {
  682. /* we don't create new namespace in complain mode */
  683. name = ns_name;
  684. info = "namespace not found";
  685. error = -ENOENT;
  686. goto audit;
  687. }
  688. } else
  689. /* released below */
  690. ns = aa_get_namespace(profile->ns);
  691. /* if the name was not specified, use the name of the current profile */
  692. if (!hname) {
  693. if (unconfined(profile))
  694. hname = ns->unconfined->base.hname;
  695. else
  696. hname = profile->base.hname;
  697. }
  698. perms = change_profile_perms(profile, ns, hname, request,
  699. profile->file.start);
  700. if (!(perms.allow & request)) {
  701. error = -EACCES;
  702. goto audit;
  703. }
  704. /* released below */
  705. target = aa_lookup_profile(ns, hname);
  706. if (!target) {
  707. info = "profile not found";
  708. error = -ENOENT;
  709. if (permtest || !COMPLAIN_MODE(profile))
  710. goto audit;
  711. /* released below */
  712. target = aa_new_null_profile(profile, 0);
  713. if (!target) {
  714. info = "failed null profile create";
  715. error = -ENOMEM;
  716. goto audit;
  717. }
  718. }
  719. /* check if tracing task is allowed to trace target domain */
  720. error = may_change_ptraced_domain(current, target);
  721. if (error) {
  722. info = "ptrace prevents transition";
  723. goto audit;
  724. }
  725. if (permtest)
  726. goto audit;
  727. if (onexec)
  728. error = aa_set_current_onexec(target);
  729. else
  730. error = aa_replace_current_profile(target);
  731. audit:
  732. if (!permtest)
  733. error = aa_audit_file(profile, &perms, GFP_KERNEL, op, request,
  734. name, hname, 0, info, error);
  735. aa_put_namespace(ns);
  736. aa_put_profile(target);
  737. put_cred(cred);
  738. return error;
  739. }