aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Johansen <john.johansen@canonical.com>2017-05-26 19:45:48 -0400
committerJohn Johansen <john.johansen@canonical.com>2017-06-10 20:11:27 -0400
commit4ae47f33354a96efb4e4231dec0d72a586b3921c (patch)
tree9d75fc20d9fd75333595aaa17e738087aa6912dc
parentd9bf2c268be6064ae0c9980e4c37fdd262c7effc (diff)
apparmor: add mkdir/rmdir interface to manage policy namespaces
When setting up namespaces for containers its easier for them to use an fs interface to create the namespace for the containers policy. Allow mkdir/rmdir under the policy/namespaces/ dir to be used to create and remove namespaces. BugLink: http://bugs.launchpad.net/bugs/1611078 Signed-off-by: John Johansen <john.johansen@canonical.com>
-rw-r--r--security/apparmor/apparmorfs.c95
1 files changed, 94 insertions, 1 deletions
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
index 8c413333726b..7f3049300ce3 100644
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -1322,6 +1322,97 @@ fail2:
1322 return error; 1322 return error;
1323} 1323}
1324 1324
1325static int ns_mkdir_op(struct inode *dir, struct dentry *dentry, umode_t mode)
1326{
1327 struct aa_ns *ns, *parent;
1328 /* TODO: improve permission check */
1329 struct aa_profile *profile = aa_current_profile();
1330 int error = aa_may_manage_policy(profile, NULL, AA_MAY_LOAD_POLICY);
1331
1332 if (error)
1333 return error;
1334
1335 parent = aa_get_ns(dir->i_private);
1336 AA_BUG(d_inode(ns_subns_dir(parent)) != dir);
1337
1338 /* we have to unlock and then relock to get locking order right
1339 * for pin_fs
1340 */
1341 inode_unlock(dir);
1342 error = simple_pin_fs(&aafs_ops, &aafs_mnt, &aafs_count);
1343 mutex_lock(&parent->lock);
1344 inode_lock_nested(dir, I_MUTEX_PARENT);
1345 if (error)
1346 goto out;
1347
1348 error = __aafs_setup_d_inode(dir, dentry, mode | S_IFDIR, NULL,
1349 NULL, NULL, NULL);
1350 if (error)
1351 goto out_pin;
1352
1353 ns = __aa_find_or_create_ns(parent, READ_ONCE(dentry->d_name.name),
1354 dentry);
1355 if (IS_ERR(ns)) {
1356 error = PTR_ERR(ns);
1357 ns = NULL;
1358 }
1359
1360 aa_put_ns(ns); /* list ref remains */
1361out_pin:
1362 if (error)
1363 simple_release_fs(&aafs_mnt, &aafs_count);
1364out:
1365 mutex_unlock(&parent->lock);
1366 aa_put_ns(parent);
1367
1368 return error;
1369}
1370
1371static int ns_rmdir_op(struct inode *dir, struct dentry *dentry)
1372{
1373 struct aa_ns *ns, *parent;
1374 /* TODO: improve permission check */
1375 struct aa_profile *profile = aa_current_profile();
1376 int error = aa_may_manage_policy(profile, NULL, AA_MAY_LOAD_POLICY);
1377
1378 if (error)
1379 return error;
1380
1381 parent = aa_get_ns(dir->i_private);
1382 /* rmdir calls the generic securityfs functions to remove files
1383 * from the apparmor dir. It is up to the apparmor ns locking
1384 * to avoid races.
1385 */
1386 inode_unlock(dir);
1387 inode_unlock(dentry->d_inode);
1388
1389 mutex_lock(&parent->lock);
1390 ns = aa_get_ns(__aa_findn_ns(&parent->sub_ns, dentry->d_name.name,
1391 dentry->d_name.len));
1392 if (!ns) {
1393 error = -ENOENT;
1394 goto out;
1395 }
1396 AA_BUG(ns_dir(ns) != dentry);
1397
1398 __aa_remove_ns(ns);
1399 aa_put_ns(ns);
1400
1401out:
1402 mutex_unlock(&parent->lock);
1403 inode_lock_nested(dir, I_MUTEX_PARENT);
1404 inode_lock(dentry->d_inode);
1405 aa_put_ns(parent);
1406
1407 return error;
1408}
1409
1410static const struct inode_operations ns_dir_inode_operations = {
1411 .lookup = simple_lookup,
1412 .mkdir = ns_mkdir_op,
1413 .rmdir = ns_rmdir_op,
1414};
1415
1325static void __aa_fs_list_remove_rawdata(struct aa_ns *ns) 1416static void __aa_fs_list_remove_rawdata(struct aa_ns *ns)
1326{ 1417{
1327 struct aa_loaddata *ent, *tmp; 1418 struct aa_loaddata *ent, *tmp;
@@ -1429,7 +1520,9 @@ static int __aafs_ns_mkdir_entries(struct aa_ns *ns, struct dentry *dir)
1429 aa_get_ns(ns); 1520 aa_get_ns(ns);
1430 ns_subremove(ns) = dent; 1521 ns_subremove(ns) = dent;
1431 1522
1432 dent = aafs_create_dir("namespaces", dir); 1523 /* use create_dentry so we can supply private data */
1524 dent = aafs_create("namespaces", S_IFDIR | 0755, dir, ns, NULL, NULL,
1525 &ns_dir_inode_operations);
1433 if (IS_ERR(dent)) 1526 if (IS_ERR(dent))
1434 return PTR_ERR(dent); 1527 return PTR_ERR(dent);
1435 aa_get_ns(ns); 1528 aa_get_ns(ns);