@@ -336,12 +336,9 @@ static struct dentry *sel_make_dir(struct dentry *dir, const char *name,
336336 unsigned long * ino );
337337
338338/* declaration for sel_make_policy_nodes */
339- static struct dentry * sel_make_disconnected_dir (struct super_block * sb ,
339+ static struct dentry * sel_make_swapover_dir (struct super_block * sb ,
340340 unsigned long * ino );
341341
342- /* declaration for sel_make_policy_nodes */
343- static void sel_remove_entries (struct dentry * de );
344-
345342static ssize_t sel_read_mls (struct file * filp , char __user * buf ,
346343 size_t count , loff_t * ppos )
347344{
@@ -508,13 +505,13 @@ static int sel_make_policy_nodes(struct selinux_fs_info *fsi,
508505 struct selinux_policy * newpolicy )
509506{
510507 int ret = 0 ;
511- struct dentry * tmp_parent , * tmp_bool_dir , * tmp_class_dir , * old_dentry ;
512- unsigned int tmp_bool_num , old_bool_num ;
513- char * * tmp_bool_names , * * old_bool_names ;
514- int * tmp_bool_values , * old_bool_values ;
508+ struct dentry * tmp_parent , * tmp_bool_dir , * tmp_class_dir ;
509+ unsigned int bool_num = 0 ;
510+ char * * bool_names = NULL ;
511+ int * bool_values = NULL ;
515512 unsigned long tmp_ino = fsi -> last_ino ; /* Don't increment last_ino in this function */
516513
517- tmp_parent = sel_make_disconnected_dir (fsi -> sb , & tmp_ino );
514+ tmp_parent = sel_make_swapover_dir (fsi -> sb , & tmp_ino );
518515 if (IS_ERR (tmp_parent ))
519516 return PTR_ERR (tmp_parent );
520517
@@ -532,8 +529,8 @@ static int sel_make_policy_nodes(struct selinux_fs_info *fsi,
532529 goto out ;
533530 }
534531
535- ret = sel_make_bools (newpolicy , tmp_bool_dir , & tmp_bool_num ,
536- & tmp_bool_names , & tmp_bool_values );
532+ ret = sel_make_bools (newpolicy , tmp_bool_dir , & bool_num ,
533+ & bool_names , & bool_values );
537534 if (ret )
538535 goto out ;
539536
@@ -542,38 +539,30 @@ static int sel_make_policy_nodes(struct selinux_fs_info *fsi,
542539 if (ret )
543540 goto out ;
544541
542+ lock_rename (tmp_parent , fsi -> sb -> s_root );
543+
545544 /* booleans */
546- old_dentry = fsi -> bool_dir ;
547- lock_rename (tmp_bool_dir , old_dentry );
548545 d_exchange (tmp_bool_dir , fsi -> bool_dir );
549546
550- old_bool_num = fsi -> bool_num ;
551- old_bool_names = fsi -> bool_pending_names ;
552- old_bool_values = fsi -> bool_pending_values ;
553-
554- fsi -> bool_num = tmp_bool_num ;
555- fsi -> bool_pending_names = tmp_bool_names ;
556- fsi -> bool_pending_values = tmp_bool_values ;
557-
558- sel_remove_old_bool_data (old_bool_num , old_bool_names , old_bool_values );
547+ swap (fsi -> bool_num , bool_num );
548+ swap (fsi -> bool_pending_names , bool_names );
549+ swap (fsi -> bool_pending_values , bool_values );
559550
560551 fsi -> bool_dir = tmp_bool_dir ;
561- unlock_rename (tmp_bool_dir , old_dentry );
562552
563553 /* classes */
564- old_dentry = fsi -> class_dir ;
565- lock_rename (tmp_class_dir , old_dentry );
566554 d_exchange (tmp_class_dir , fsi -> class_dir );
567555 fsi -> class_dir = tmp_class_dir ;
568- unlock_rename (tmp_class_dir , old_dentry );
556+
557+ unlock_rename (tmp_parent , fsi -> sb -> s_root );
569558
570559out :
560+ sel_remove_old_bool_data (bool_num , bool_names , bool_values );
571561 /* Since the other temporary dirs are children of tmp_parent
572562 * this will handle all the cleanup in the case of a failure before
573563 * the swapover
574564 */
575- sel_remove_entries (tmp_parent );
576- dput (tmp_parent ); /* d_genocide() only handles the children */
565+ simple_recursive_removal (tmp_parent , NULL );
577566
578567 return ret ;
579568}
@@ -1351,54 +1340,48 @@ static const struct file_operations sel_commit_bools_ops = {
13511340 .llseek = generic_file_llseek ,
13521341};
13531342
1354- static void sel_remove_entries (struct dentry * de )
1355- {
1356- d_genocide (de );
1357- shrink_dcache_parent (de );
1358- }
1359-
13601343static int sel_make_bools (struct selinux_policy * newpolicy , struct dentry * bool_dir ,
13611344 unsigned int * bool_num , char * * * bool_pending_names ,
13621345 int * * bool_pending_values )
13631346{
13641347 int ret ;
1365- ssize_t len ;
1366- struct dentry * dentry = NULL ;
1367- struct inode * inode = NULL ;
1368- struct inode_security_struct * isec ;
1369- char * * names = NULL , * page ;
1348+ char * * names , * page ;
13701349 u32 i , num ;
1371- int * values = NULL ;
1372- u32 sid ;
13731350
1374- ret = - ENOMEM ;
13751351 page = (char * )get_zeroed_page (GFP_KERNEL );
13761352 if (!page )
1377- goto out ;
1353+ return - ENOMEM ;
13781354
1379- ret = security_get_bools (newpolicy , & num , & names , & values );
1355+ ret = security_get_bools (newpolicy , & num , & names , bool_pending_values );
13801356 if (ret )
13811357 goto out ;
13821358
1359+ * bool_num = num ;
1360+ * bool_pending_names = names ;
1361+
13831362 for (i = 0 ; i < num ; i ++ ) {
1384- ret = - ENOMEM ;
1363+ struct dentry * dentry ;
1364+ struct inode * inode ;
1365+ struct inode_security_struct * isec ;
1366+ ssize_t len ;
1367+ u32 sid ;
1368+
1369+ len = snprintf (page , PAGE_SIZE , "/%s/%s" , BOOL_DIR_NAME , names [i ]);
1370+ if (len >= PAGE_SIZE ) {
1371+ ret = - ENAMETOOLONG ;
1372+ break ;
1373+ }
13851374 dentry = d_alloc_name (bool_dir , names [i ]);
1386- if (!dentry )
1387- goto out ;
1375+ if (!dentry ) {
1376+ ret = - ENOMEM ;
1377+ break ;
1378+ }
13881379
1389- ret = - ENOMEM ;
13901380 inode = sel_make_inode (bool_dir -> d_sb , S_IFREG | S_IRUGO | S_IWUSR );
13911381 if (!inode ) {
13921382 dput (dentry );
1393- goto out ;
1394- }
1395-
1396- ret = - ENAMETOOLONG ;
1397- len = snprintf (page , PAGE_SIZE , "/%s/%s" , BOOL_DIR_NAME , names [i ]);
1398- if (len >= PAGE_SIZE ) {
1399- dput (dentry );
1400- iput (inode );
1401- goto out ;
1383+ ret = - ENOMEM ;
1384+ break ;
14021385 }
14031386
14041387 isec = selinux_inode (inode );
@@ -1416,23 +1399,8 @@ static int sel_make_bools(struct selinux_policy *newpolicy, struct dentry *bool_
14161399 inode -> i_ino = i |SEL_BOOL_INO_OFFSET ;
14171400 d_add (dentry , inode );
14181401 }
1419- * bool_num = num ;
1420- * bool_pending_names = names ;
1421- * bool_pending_values = values ;
1422-
1423- free_page ((unsigned long )page );
1424- return 0 ;
14251402out :
14261403 free_page ((unsigned long )page );
1427-
1428- if (names ) {
1429- for (i = 0 ; i < num ; i ++ )
1430- kfree (names [i ]);
1431- kfree (names );
1432- }
1433- kfree (values );
1434- sel_remove_entries (bool_dir );
1435-
14361404 return ret ;
14371405}
14381406
@@ -1961,20 +1929,40 @@ static struct dentry *sel_make_dir(struct dentry *dir, const char *name,
19611929 return dentry ;
19621930}
19631931
1964- static struct dentry * sel_make_disconnected_dir (struct super_block * sb ,
1932+ static int reject_all (struct mnt_idmap * idmap , struct inode * inode , int mask )
1933+ {
1934+ return - EPERM ; // no access for anyone, root or no root.
1935+ }
1936+
1937+ static const struct inode_operations swapover_dir_inode_operations = {
1938+ .lookup = simple_lookup ,
1939+ .permission = reject_all ,
1940+ };
1941+
1942+ static struct dentry * sel_make_swapover_dir (struct super_block * sb ,
19651943 unsigned long * ino )
19661944{
1967- struct inode * inode = sel_make_inode (sb , S_IFDIR | S_IRUGO | S_IXUGO );
1945+ struct dentry * dentry = d_alloc_name (sb -> s_root , ".swapover" );
1946+ struct inode * inode ;
19681947
1969- if (!inode )
1948+ if (!dentry )
19701949 return ERR_PTR (- ENOMEM );
19711950
1972- inode -> i_op = & simple_dir_inode_operations ;
1973- inode -> i_fop = & simple_dir_operations ;
1951+ inode = sel_make_inode (sb , S_IFDIR );
1952+ if (!inode ) {
1953+ dput (dentry );
1954+ return ERR_PTR (- ENOMEM );
1955+ }
1956+
1957+ inode -> i_op = & swapover_dir_inode_operations ;
19741958 inode -> i_ino = ++ (* ino );
19751959 /* directory inodes start off with i_nlink == 2 (for "." entry) */
19761960 inc_nlink (inode );
1977- return d_obtain_alias (inode );
1961+ inode_lock (sb -> s_root -> d_inode );
1962+ d_add (dentry , inode );
1963+ inc_nlink (sb -> s_root -> d_inode );
1964+ inode_unlock (sb -> s_root -> d_inode );
1965+ return dentry ;
19781966}
19791967
19801968#define NULL_FILE_NAME "null"
0 commit comments