mount.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * AppArmor security module
  4. *
  5. * This file contains AppArmor mediation of files
  6. *
  7. * Copyright (C) 1998-2008 Novell/SUSE
  8. * Copyright 2009-2017 Canonical Ltd.
  9. */
  10. #include <linux/fs.h>
  11. #include <linux/mount.h>
  12. #include <linux/namei.h>
  13. #include <uapi/linux/mount.h>
  14. #include "include/apparmor.h"
  15. #include "include/audit.h"
  16. #include "include/cred.h"
  17. #include "include/domain.h"
  18. #include "include/file.h"
  19. #include "include/match.h"
  20. #include "include/mount.h"
  21. #include "include/path.h"
  22. #include "include/policy.h"
  23. static void audit_mnt_flags(struct audit_buffer *ab, unsigned long flags)
  24. {
  25. if (flags & MS_RDONLY)
  26. audit_log_format(ab, "ro");
  27. else
  28. audit_log_format(ab, "rw");
  29. if (flags & MS_NOSUID)
  30. audit_log_format(ab, ", nosuid");
  31. if (flags & MS_NODEV)
  32. audit_log_format(ab, ", nodev");
  33. if (flags & MS_NOEXEC)
  34. audit_log_format(ab, ", noexec");
  35. if (flags & MS_SYNCHRONOUS)
  36. audit_log_format(ab, ", sync");
  37. if (flags & MS_REMOUNT)
  38. audit_log_format(ab, ", remount");
  39. if (flags & MS_MANDLOCK)
  40. audit_log_format(ab, ", mand");
  41. if (flags & MS_DIRSYNC)
  42. audit_log_format(ab, ", dirsync");
  43. if (flags & MS_NOATIME)
  44. audit_log_format(ab, ", noatime");
  45. if (flags & MS_NODIRATIME)
  46. audit_log_format(ab, ", nodiratime");
  47. if (flags & MS_BIND)
  48. audit_log_format(ab, flags & MS_REC ? ", rbind" : ", bind");
  49. if (flags & MS_MOVE)
  50. audit_log_format(ab, ", move");
  51. if (flags & MS_SILENT)
  52. audit_log_format(ab, ", silent");
  53. if (flags & MS_POSIXACL)
  54. audit_log_format(ab, ", acl");
  55. if (flags & MS_UNBINDABLE)
  56. audit_log_format(ab, flags & MS_REC ? ", runbindable" :
  57. ", unbindable");
  58. if (flags & MS_PRIVATE)
  59. audit_log_format(ab, flags & MS_REC ? ", rprivate" :
  60. ", private");
  61. if (flags & MS_SLAVE)
  62. audit_log_format(ab, flags & MS_REC ? ", rslave" :
  63. ", slave");
  64. if (flags & MS_SHARED)
  65. audit_log_format(ab, flags & MS_REC ? ", rshared" :
  66. ", shared");
  67. if (flags & MS_RELATIME)
  68. audit_log_format(ab, ", relatime");
  69. if (flags & MS_I_VERSION)
  70. audit_log_format(ab, ", iversion");
  71. if (flags & MS_STRICTATIME)
  72. audit_log_format(ab, ", strictatime");
  73. if (flags & MS_NOUSER)
  74. audit_log_format(ab, ", nouser");
  75. }
  76. /**
  77. * audit_cb - call back for mount specific audit fields
  78. * @ab: audit_buffer (NOT NULL)
  79. * @va: audit struct to audit values of (NOT NULL)
  80. */
  81. static void audit_cb(struct audit_buffer *ab, void *va)
  82. {
  83. struct common_audit_data *sa = va;
  84. if (aad(sa)->mnt.type) {
  85. audit_log_format(ab, " fstype=");
  86. audit_log_untrustedstring(ab, aad(sa)->mnt.type);
  87. }
  88. if (aad(sa)->mnt.src_name) {
  89. audit_log_format(ab, " srcname=");
  90. audit_log_untrustedstring(ab, aad(sa)->mnt.src_name);
  91. }
  92. if (aad(sa)->mnt.trans) {
  93. audit_log_format(ab, " trans=");
  94. audit_log_untrustedstring(ab, aad(sa)->mnt.trans);
  95. }
  96. if (aad(sa)->mnt.flags) {
  97. audit_log_format(ab, " flags=\"");
  98. audit_mnt_flags(ab, aad(sa)->mnt.flags);
  99. audit_log_format(ab, "\"");
  100. }
  101. if (aad(sa)->mnt.data) {
  102. audit_log_format(ab, " options=");
  103. audit_log_untrustedstring(ab, aad(sa)->mnt.data);
  104. }
  105. }
  106. /**
  107. * audit_mount - handle the auditing of mount operations
  108. * @profile: the profile being enforced (NOT NULL)
  109. * @op: operation being mediated (NOT NULL)
  110. * @name: name of object being mediated (MAYBE NULL)
  111. * @src_name: src_name of object being mediated (MAYBE_NULL)
  112. * @type: type of filesystem (MAYBE_NULL)
  113. * @trans: name of trans (MAYBE NULL)
  114. * @flags: filesystem independent mount flags
  115. * @data: filesystem mount flags
  116. * @request: permissions requested
  117. * @perms: the permissions computed for the request (NOT NULL)
  118. * @info: extra information message (MAYBE NULL)
  119. * @error: 0 if operation allowed else failure error code
  120. *
  121. * Returns: %0 or error on failure
  122. */
  123. static int audit_mount(struct aa_profile *profile, const char *op,
  124. const char *name, const char *src_name,
  125. const char *type, const char *trans,
  126. unsigned long flags, const void *data, u32 request,
  127. struct aa_perms *perms, const char *info, int error)
  128. {
  129. int audit_type = AUDIT_APPARMOR_AUTO;
  130. DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, op);
  131. if (likely(!error)) {
  132. u32 mask = perms->audit;
  133. if (unlikely(AUDIT_MODE(profile) == AUDIT_ALL))
  134. mask = 0xffff;
  135. /* mask off perms that are not being force audited */
  136. request &= mask;
  137. if (likely(!request))
  138. return 0;
  139. audit_type = AUDIT_APPARMOR_AUDIT;
  140. } else {
  141. /* only report permissions that were denied */
  142. request = request & ~perms->allow;
  143. if (request & perms->kill)
  144. audit_type = AUDIT_APPARMOR_KILL;
  145. /* quiet known rejects, assumes quiet and kill do not overlap */
  146. if ((request & perms->quiet) &&
  147. AUDIT_MODE(profile) != AUDIT_NOQUIET &&
  148. AUDIT_MODE(profile) != AUDIT_ALL)
  149. request &= ~perms->quiet;
  150. if (!request)
  151. return error;
  152. }
  153. aad(&sa)->name = name;
  154. aad(&sa)->mnt.src_name = src_name;
  155. aad(&sa)->mnt.type = type;
  156. aad(&sa)->mnt.trans = trans;
  157. aad(&sa)->mnt.flags = flags;
  158. if (data && (perms->audit & AA_AUDIT_DATA))
  159. aad(&sa)->mnt.data = data;
  160. aad(&sa)->info = info;
  161. aad(&sa)->error = error;
  162. return aa_audit(audit_type, profile, &sa, audit_cb);
  163. }
  164. /**
  165. * match_mnt_flags - Do an ordered match on mount flags
  166. * @dfa: dfa to match against
  167. * @state: state to start in
  168. * @flags: mount flags to match against
  169. *
  170. * Mount flags are encoded as an ordered match. This is done instead of
  171. * checking against a simple bitmask, to allow for logical operations
  172. * on the flags.
  173. *
  174. * Returns: next state after flags match
  175. */
  176. static unsigned int match_mnt_flags(struct aa_dfa *dfa, unsigned int state,
  177. unsigned long flags)
  178. {
  179. unsigned int i;
  180. for (i = 0; i <= 31 ; ++i) {
  181. if ((1 << i) & flags)
  182. state = aa_dfa_next(dfa, state, i + 1);
  183. }
  184. return state;
  185. }
  186. /**
  187. * compute_mnt_perms - compute mount permission associated with @state
  188. * @dfa: dfa to match against (NOT NULL)
  189. * @state: state match finished in
  190. *
  191. * Returns: mount permissions
  192. */
  193. static struct aa_perms compute_mnt_perms(struct aa_dfa *dfa,
  194. unsigned int state)
  195. {
  196. struct aa_perms perms = {
  197. .allow = dfa_user_allow(dfa, state),
  198. .audit = dfa_user_audit(dfa, state),
  199. .quiet = dfa_user_quiet(dfa, state),
  200. };
  201. return perms;
  202. }
  203. static const char * const mnt_info_table[] = {
  204. "match succeeded",
  205. "failed mntpnt match",
  206. "failed srcname match",
  207. "failed type match",
  208. "failed flags match",
  209. "failed data match",
  210. "failed perms check"
  211. };
  212. /*
  213. * Returns 0 on success else element that match failed in, this is the
  214. * index into the mnt_info_table above
  215. */
  216. static int do_match_mnt(struct aa_dfa *dfa, unsigned int start,
  217. const char *mntpnt, const char *devname,
  218. const char *type, unsigned long flags,
  219. void *data, bool binary, struct aa_perms *perms)
  220. {
  221. unsigned int state;
  222. AA_BUG(!dfa);
  223. AA_BUG(!perms);
  224. state = aa_dfa_match(dfa, start, mntpnt);
  225. state = aa_dfa_null_transition(dfa, state);
  226. if (!state)
  227. return 1;
  228. if (devname)
  229. state = aa_dfa_match(dfa, state, devname);
  230. state = aa_dfa_null_transition(dfa, state);
  231. if (!state)
  232. return 2;
  233. if (type)
  234. state = aa_dfa_match(dfa, state, type);
  235. state = aa_dfa_null_transition(dfa, state);
  236. if (!state)
  237. return 3;
  238. state = match_mnt_flags(dfa, state, flags);
  239. if (!state)
  240. return 4;
  241. *perms = compute_mnt_perms(dfa, state);
  242. if (perms->allow & AA_MAY_MOUNT)
  243. return 0;
  244. /* only match data if not binary and the DFA flags data is expected */
  245. if (data && !binary && (perms->allow & AA_MNT_CONT_MATCH)) {
  246. state = aa_dfa_null_transition(dfa, state);
  247. if (!state)
  248. return 4;
  249. state = aa_dfa_match(dfa, state, data);
  250. if (!state)
  251. return 5;
  252. *perms = compute_mnt_perms(dfa, state);
  253. if (perms->allow & AA_MAY_MOUNT)
  254. return 0;
  255. }
  256. /* failed at perms check, don't confuse with flags match */
  257. return 6;
  258. }
  259. static int path_flags(struct aa_profile *profile, const struct path *path)
  260. {
  261. AA_BUG(!profile);
  262. AA_BUG(!path);
  263. return profile->path_flags |
  264. (S_ISDIR(path->dentry->d_inode->i_mode) ? PATH_IS_DIR : 0);
  265. }
  266. /**
  267. * match_mnt_path_str - handle path matching for mount
  268. * @profile: the confining profile
  269. * @mntpath: for the mntpnt (NOT NULL)
  270. * @buffer: buffer to be used to lookup mntpath
  271. * @devname: string for the devname/src_name (MAY BE NULL OR ERRPTR)
  272. * @type: string for the dev type (MAYBE NULL)
  273. * @flags: mount flags to match
  274. * @data: fs mount data (MAYBE NULL)
  275. * @binary: whether @data is binary
  276. * @devinfo: error str if (IS_ERR(@devname))
  277. *
  278. * Returns: 0 on success else error
  279. */
  280. static int match_mnt_path_str(struct aa_profile *profile,
  281. const struct path *mntpath, char *buffer,
  282. const char *devname, const char *type,
  283. unsigned long flags, void *data, bool binary,
  284. const char *devinfo)
  285. {
  286. struct aa_perms perms = { };
  287. const char *mntpnt = NULL, *info = NULL;
  288. int pos, error;
  289. AA_BUG(!profile);
  290. AA_BUG(!mntpath);
  291. AA_BUG(!buffer);
  292. if (!PROFILE_MEDIATES(profile, AA_CLASS_MOUNT))
  293. return 0;
  294. error = aa_path_name(mntpath, path_flags(profile, mntpath), buffer,
  295. &mntpnt, &info, profile->disconnected);
  296. if (error)
  297. goto audit;
  298. if (IS_ERR(devname)) {
  299. error = PTR_ERR(devname);
  300. devname = NULL;
  301. info = devinfo;
  302. goto audit;
  303. }
  304. error = -EACCES;
  305. pos = do_match_mnt(profile->policy.dfa,
  306. profile->policy.start[AA_CLASS_MOUNT],
  307. mntpnt, devname, type, flags, data, binary, &perms);
  308. if (pos) {
  309. info = mnt_info_table[pos];
  310. goto audit;
  311. }
  312. error = 0;
  313. audit:
  314. return audit_mount(profile, OP_MOUNT, mntpnt, devname, type, NULL,
  315. flags, data, AA_MAY_MOUNT, &perms, info, error);
  316. }
  317. /**
  318. * match_mnt - handle path matching for mount
  319. * @profile: the confining profile
  320. * @path: for the mntpnt (NOT NULL)
  321. * @buffer: buffer to be used to lookup mntpath
  322. * @devpath: path devname/src_name (MAYBE NULL)
  323. * @devbuffer: buffer to be used to lookup devname/src_name
  324. * @type: string for the dev type (MAYBE NULL)
  325. * @flags: mount flags to match
  326. * @data: fs mount data (MAYBE NULL)
  327. * @binary: whether @data is binary
  328. *
  329. * Returns: 0 on success else error
  330. */
  331. static int match_mnt(struct aa_profile *profile, const struct path *path,
  332. char *buffer, const struct path *devpath, char *devbuffer,
  333. const char *type, unsigned long flags, void *data,
  334. bool binary)
  335. {
  336. const char *devname = NULL, *info = NULL;
  337. int error = -EACCES;
  338. AA_BUG(!profile);
  339. AA_BUG(devpath && !devbuffer);
  340. if (!PROFILE_MEDIATES(profile, AA_CLASS_MOUNT))
  341. return 0;
  342. if (devpath) {
  343. error = aa_path_name(devpath, path_flags(profile, devpath),
  344. devbuffer, &devname, &info,
  345. profile->disconnected);
  346. if (error)
  347. devname = ERR_PTR(error);
  348. }
  349. return match_mnt_path_str(profile, path, buffer, devname, type, flags,
  350. data, binary, info);
  351. }
  352. int aa_remount(struct aa_label *label, const struct path *path,
  353. unsigned long flags, void *data)
  354. {
  355. struct aa_profile *profile;
  356. char *buffer = NULL;
  357. bool binary;
  358. int error;
  359. AA_BUG(!label);
  360. AA_BUG(!path);
  361. binary = path->dentry->d_sb->s_type->fs_flags & FS_BINARY_MOUNTDATA;
  362. buffer = aa_get_buffer(false);
  363. if (!buffer)
  364. return -ENOMEM;
  365. error = fn_for_each_confined(label, profile,
  366. match_mnt(profile, path, buffer, NULL, NULL, NULL,
  367. flags, data, binary));
  368. aa_put_buffer(buffer);
  369. return error;
  370. }
  371. int aa_bind_mount(struct aa_label *label, const struct path *path,
  372. const char *dev_name, unsigned long flags)
  373. {
  374. struct aa_profile *profile;
  375. char *buffer = NULL, *old_buffer = NULL;
  376. struct path old_path;
  377. int error;
  378. AA_BUG(!label);
  379. AA_BUG(!path);
  380. if (!dev_name || !*dev_name)
  381. return -EINVAL;
  382. flags &= MS_REC | MS_BIND;
  383. error = kern_path(dev_name, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &old_path);
  384. if (error)
  385. return error;
  386. buffer = aa_get_buffer(false);
  387. old_buffer = aa_get_buffer(false);
  388. error = -ENOMEM;
  389. if (!buffer || !old_buffer)
  390. goto out;
  391. error = fn_for_each_confined(label, profile,
  392. match_mnt(profile, path, buffer, &old_path, old_buffer,
  393. NULL, flags, NULL, false));
  394. out:
  395. aa_put_buffer(buffer);
  396. aa_put_buffer(old_buffer);
  397. path_put(&old_path);
  398. return error;
  399. }
  400. int aa_mount_change_type(struct aa_label *label, const struct path *path,
  401. unsigned long flags)
  402. {
  403. struct aa_profile *profile;
  404. char *buffer = NULL;
  405. int error;
  406. AA_BUG(!label);
  407. AA_BUG(!path);
  408. /* These are the flags allowed by do_change_type() */
  409. flags &= (MS_REC | MS_SILENT | MS_SHARED | MS_PRIVATE | MS_SLAVE |
  410. MS_UNBINDABLE);
  411. buffer = aa_get_buffer(false);
  412. if (!buffer)
  413. return -ENOMEM;
  414. error = fn_for_each_confined(label, profile,
  415. match_mnt(profile, path, buffer, NULL, NULL, NULL,
  416. flags, NULL, false));
  417. aa_put_buffer(buffer);
  418. return error;
  419. }
  420. int aa_move_mount(struct aa_label *label, const struct path *path,
  421. const char *orig_name)
  422. {
  423. struct aa_profile *profile;
  424. char *buffer = NULL, *old_buffer = NULL;
  425. struct path old_path;
  426. int error;
  427. AA_BUG(!label);
  428. AA_BUG(!path);
  429. if (!orig_name || !*orig_name)
  430. return -EINVAL;
  431. error = kern_path(orig_name, LOOKUP_FOLLOW, &old_path);
  432. if (error)
  433. return error;
  434. buffer = aa_get_buffer(false);
  435. old_buffer = aa_get_buffer(false);
  436. error = -ENOMEM;
  437. if (!buffer || !old_buffer)
  438. goto out;
  439. error = fn_for_each_confined(label, profile,
  440. match_mnt(profile, path, buffer, &old_path, old_buffer,
  441. NULL, MS_MOVE, NULL, false));
  442. out:
  443. aa_put_buffer(buffer);
  444. aa_put_buffer(old_buffer);
  445. path_put(&old_path);
  446. return error;
  447. }
  448. int aa_new_mount(struct aa_label *label, const char *dev_name,
  449. const struct path *path, const char *type, unsigned long flags,
  450. void *data)
  451. {
  452. struct aa_profile *profile;
  453. char *buffer = NULL, *dev_buffer = NULL;
  454. bool binary = true;
  455. int error;
  456. int requires_dev = 0;
  457. struct path tmp_path, *dev_path = NULL;
  458. AA_BUG(!label);
  459. AA_BUG(!path);
  460. if (type) {
  461. struct file_system_type *fstype;
  462. fstype = get_fs_type(type);
  463. if (!fstype)
  464. return -ENODEV;
  465. binary = fstype->fs_flags & FS_BINARY_MOUNTDATA;
  466. requires_dev = fstype->fs_flags & FS_REQUIRES_DEV;
  467. put_filesystem(fstype);
  468. if (requires_dev) {
  469. if (!dev_name || !*dev_name)
  470. return -ENOENT;
  471. error = kern_path(dev_name, LOOKUP_FOLLOW, &tmp_path);
  472. if (error)
  473. return error;
  474. dev_path = &tmp_path;
  475. }
  476. }
  477. buffer = aa_get_buffer(false);
  478. if (!buffer) {
  479. error = -ENOMEM;
  480. goto out;
  481. }
  482. if (dev_path) {
  483. dev_buffer = aa_get_buffer(false);
  484. if (!dev_buffer) {
  485. error = -ENOMEM;
  486. goto out;
  487. }
  488. error = fn_for_each_confined(label, profile,
  489. match_mnt(profile, path, buffer, dev_path, dev_buffer,
  490. type, flags, data, binary));
  491. } else {
  492. error = fn_for_each_confined(label, profile,
  493. match_mnt_path_str(profile, path, buffer, dev_name,
  494. type, flags, data, binary, NULL));
  495. }
  496. out:
  497. aa_put_buffer(buffer);
  498. aa_put_buffer(dev_buffer);
  499. if (dev_path)
  500. path_put(dev_path);
  501. return error;
  502. }
  503. static int profile_umount(struct aa_profile *profile, const struct path *path,
  504. char *buffer)
  505. {
  506. struct aa_perms perms = { };
  507. const char *name = NULL, *info = NULL;
  508. unsigned int state;
  509. int error;
  510. AA_BUG(!profile);
  511. AA_BUG(!path);
  512. if (!PROFILE_MEDIATES(profile, AA_CLASS_MOUNT))
  513. return 0;
  514. error = aa_path_name(path, path_flags(profile, path), buffer, &name,
  515. &info, profile->disconnected);
  516. if (error)
  517. goto audit;
  518. state = aa_dfa_match(profile->policy.dfa,
  519. profile->policy.start[AA_CLASS_MOUNT],
  520. name);
  521. perms = compute_mnt_perms(profile->policy.dfa, state);
  522. if (AA_MAY_UMOUNT & ~perms.allow)
  523. error = -EACCES;
  524. audit:
  525. return audit_mount(profile, OP_UMOUNT, name, NULL, NULL, NULL, 0, NULL,
  526. AA_MAY_UMOUNT, &perms, info, error);
  527. }
  528. int aa_umount(struct aa_label *label, struct vfsmount *mnt, int flags)
  529. {
  530. struct aa_profile *profile;
  531. char *buffer = NULL;
  532. int error;
  533. struct path path = { .mnt = mnt, .dentry = mnt->mnt_root };
  534. AA_BUG(!label);
  535. AA_BUG(!mnt);
  536. buffer = aa_get_buffer(false);
  537. if (!buffer)
  538. return -ENOMEM;
  539. error = fn_for_each_confined(label, profile,
  540. profile_umount(profile, &path, buffer));
  541. aa_put_buffer(buffer);
  542. return error;
  543. }
  544. /* helper fn for transition on pivotroot
  545. *
  546. * Returns: label for transition or ERR_PTR. Does not return NULL
  547. */
  548. static struct aa_label *build_pivotroot(struct aa_profile *profile,
  549. const struct path *new_path,
  550. char *new_buffer,
  551. const struct path *old_path,
  552. char *old_buffer)
  553. {
  554. const char *old_name, *new_name = NULL, *info = NULL;
  555. const char *trans_name = NULL;
  556. struct aa_perms perms = { };
  557. unsigned int state;
  558. int error;
  559. AA_BUG(!profile);
  560. AA_BUG(!new_path);
  561. AA_BUG(!old_path);
  562. if (profile_unconfined(profile) ||
  563. !PROFILE_MEDIATES(profile, AA_CLASS_MOUNT))
  564. return aa_get_newest_label(&profile->label);
  565. error = aa_path_name(old_path, path_flags(profile, old_path),
  566. old_buffer, &old_name, &info,
  567. profile->disconnected);
  568. if (error)
  569. goto audit;
  570. error = aa_path_name(new_path, path_flags(profile, new_path),
  571. new_buffer, &new_name, &info,
  572. profile->disconnected);
  573. if (error)
  574. goto audit;
  575. error = -EACCES;
  576. state = aa_dfa_match(profile->policy.dfa,
  577. profile->policy.start[AA_CLASS_MOUNT],
  578. new_name);
  579. state = aa_dfa_null_transition(profile->policy.dfa, state);
  580. state = aa_dfa_match(profile->policy.dfa, state, old_name);
  581. perms = compute_mnt_perms(profile->policy.dfa, state);
  582. if (AA_MAY_PIVOTROOT & perms.allow)
  583. error = 0;
  584. audit:
  585. error = audit_mount(profile, OP_PIVOTROOT, new_name, old_name,
  586. NULL, trans_name, 0, NULL, AA_MAY_PIVOTROOT,
  587. &perms, info, error);
  588. if (error)
  589. return ERR_PTR(error);
  590. return aa_get_newest_label(&profile->label);
  591. }
  592. int aa_pivotroot(struct aa_label *label, const struct path *old_path,
  593. const struct path *new_path)
  594. {
  595. struct aa_profile *profile;
  596. struct aa_label *target = NULL;
  597. char *old_buffer = NULL, *new_buffer = NULL, *info = NULL;
  598. int error;
  599. AA_BUG(!label);
  600. AA_BUG(!old_path);
  601. AA_BUG(!new_path);
  602. old_buffer = aa_get_buffer(false);
  603. new_buffer = aa_get_buffer(false);
  604. error = -ENOMEM;
  605. if (!old_buffer || !new_buffer)
  606. goto out;
  607. target = fn_label_build(label, profile, GFP_KERNEL,
  608. build_pivotroot(profile, new_path, new_buffer,
  609. old_path, old_buffer));
  610. if (!target) {
  611. info = "label build failed";
  612. error = -ENOMEM;
  613. goto fail;
  614. } else if (!IS_ERR(target)) {
  615. error = aa_replace_current_label(target);
  616. if (error) {
  617. /* TODO: audit target */
  618. aa_put_label(target);
  619. goto out;
  620. }
  621. aa_put_label(target);
  622. } else
  623. /* already audited error */
  624. error = PTR_ERR(target);
  625. out:
  626. aa_put_buffer(old_buffer);
  627. aa_put_buffer(new_buffer);
  628. return error;
  629. fail:
  630. /* TODO: add back in auditing of new_name and old_name */
  631. error = fn_for_each(label, profile,
  632. audit_mount(profile, OP_PIVOTROOT, NULL /*new_name */,
  633. NULL /* old_name */,
  634. NULL, NULL,
  635. 0, NULL, AA_MAY_PIVOTROOT, &nullperms, info,
  636. error));
  637. goto out;
  638. }