domain.c 22 KB

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