mount.c 19 KB

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