4141#include <linux/msg.h>
4242#include <linux/shm.h>
4343#include <linux/binfmts.h>
44+ #include <linux/parser.h>
4445#include "smack.h"
4546
4647#define TRANS_TRUE "TRUE"
@@ -64,6 +65,15 @@ static char *smk_bu_mess[] = {
6465 "Unconfined Object" , /* SMACK_UNCONFINED_OBJECT */
6566};
6667
68+ static const match_table_t tokens = {
69+ {Opt_fsdefault , SMK_FSDEFAULT "%s" },
70+ {Opt_fsfloor , SMK_FSFLOOR "%s" },
71+ {Opt_fshat , SMK_FSHAT "%s" },
72+ {Opt_fsroot , SMK_FSROOT "%s" },
73+ {Opt_fstransmute , SMK_FSTRANS "%s" },
74+ {Opt_error , NULL },
75+ };
76+
6777static void smk_bu_mode (int mode , char * s )
6878{
6979 int i = 0 ;
@@ -577,84 +587,201 @@ static int smack_sb_copy_data(char *orig, char *smackopts)
577587}
578588
579589/**
580- * smack_sb_kern_mount - Smack specific mount processing
590+ * smack_parse_opts_str - parse Smack specific mount options
591+ * @options: mount options string
592+ * @opts: where to store converted mount opts
593+ *
594+ * Returns 0 on success or -ENOMEM on error.
595+ *
596+ * converts Smack specific mount options to generic security option format
597+ */
598+ static int smack_parse_opts_str (char * options ,
599+ struct security_mnt_opts * opts )
600+ {
601+ char * p ;
602+ char * fsdefault = NULL , * fsfloor = NULL ;
603+ char * fshat = NULL , * fsroot = NULL , * fstransmute = NULL ;
604+ int rc = - ENOMEM , num_mnt_opts = 0 ;
605+
606+ opts -> num_mnt_opts = 0 ;
607+
608+ if (!options )
609+ return 0 ;
610+
611+ while ((p = strsep (& options , "," )) != NULL ) {
612+ int token ;
613+ substring_t args [MAX_OPT_ARGS ];
614+
615+ if (!* p )
616+ continue ;
617+
618+ token = match_token (p , tokens , args );
619+
620+ switch (token ) {
621+ case Opt_fsdefault :
622+ if (fsdefault )
623+ goto out_opt_err ;
624+ fsdefault = match_strdup (& args [0 ]);
625+ if (!fsdefault )
626+ goto out_err ;
627+ break ;
628+ case Opt_fsfloor :
629+ if (fsfloor )
630+ goto out_opt_err ;
631+ fsfloor = match_strdup (& args [0 ]);
632+ if (!fsfloor )
633+ goto out_err ;
634+ break ;
635+ case Opt_fshat :
636+ if (fshat )
637+ goto out_opt_err ;
638+ fshat = match_strdup (& args [0 ]);
639+ if (!fshat )
640+ goto out_err ;
641+ break ;
642+ case Opt_fsroot :
643+ if (fsroot )
644+ goto out_opt_err ;
645+ fsroot = match_strdup (& args [0 ]);
646+ if (!fsroot )
647+ goto out_err ;
648+ break ;
649+ case Opt_fstransmute :
650+ if (fstransmute )
651+ goto out_opt_err ;
652+ fstransmute = match_strdup (& args [0 ]);
653+ if (!fstransmute )
654+ goto out_err ;
655+ break ;
656+ default :
657+ rc = - EINVAL ;
658+ pr_warn ("Smack: unknown mount option\n" );
659+ goto out_err ;
660+ }
661+ }
662+
663+ opts -> mnt_opts = kcalloc (NUM_SMK_MNT_OPTS , sizeof (char * ), GFP_ATOMIC );
664+ if (!opts -> mnt_opts )
665+ goto out_err ;
666+
667+ opts -> mnt_opts_flags = kcalloc (NUM_SMK_MNT_OPTS , sizeof (int ),
668+ GFP_ATOMIC );
669+ if (!opts -> mnt_opts_flags ) {
670+ kfree (opts -> mnt_opts );
671+ goto out_err ;
672+ }
673+
674+ if (fsdefault ) {
675+ opts -> mnt_opts [num_mnt_opts ] = fsdefault ;
676+ opts -> mnt_opts_flags [num_mnt_opts ++ ] = FSDEFAULT_MNT ;
677+ }
678+ if (fsfloor ) {
679+ opts -> mnt_opts [num_mnt_opts ] = fsfloor ;
680+ opts -> mnt_opts_flags [num_mnt_opts ++ ] = FSFLOOR_MNT ;
681+ }
682+ if (fshat ) {
683+ opts -> mnt_opts [num_mnt_opts ] = fshat ;
684+ opts -> mnt_opts_flags [num_mnt_opts ++ ] = FSHAT_MNT ;
685+ }
686+ if (fsroot ) {
687+ opts -> mnt_opts [num_mnt_opts ] = fsroot ;
688+ opts -> mnt_opts_flags [num_mnt_opts ++ ] = FSROOT_MNT ;
689+ }
690+ if (fstransmute ) {
691+ opts -> mnt_opts [num_mnt_opts ] = fstransmute ;
692+ opts -> mnt_opts_flags [num_mnt_opts ++ ] = FSTRANS_MNT ;
693+ }
694+
695+ opts -> num_mnt_opts = num_mnt_opts ;
696+ return 0 ;
697+
698+ out_opt_err :
699+ rc = - EINVAL ;
700+ pr_warn ("Smack: duplicate mount options\n" );
701+
702+ out_err :
703+ kfree (fsdefault );
704+ kfree (fsfloor );
705+ kfree (fshat );
706+ kfree (fsroot );
707+ kfree (fstransmute );
708+ return rc ;
709+ }
710+
711+ /**
712+ * smack_set_mnt_opts - set Smack specific mount options
581713 * @sb: the file system superblock
582- * @flags: the mount flags
583- * @data: the smack mount options
714+ * @opts: Smack mount options
715+ * @kern_flags: mount option from kernel space or user space
716+ * @set_kern_flags: where to store converted mount opts
584717 *
585718 * Returns 0 on success, an error code on failure
719+ *
720+ * Allow filesystems with binary mount data to explicitly set Smack mount
721+ * labels.
586722 */
587- static int smack_sb_kern_mount (struct super_block * sb , int flags , void * data )
723+ static int smack_set_mnt_opts (struct super_block * sb ,
724+ struct security_mnt_opts * opts ,
725+ unsigned long kern_flags ,
726+ unsigned long * set_kern_flags )
588727{
589728 struct dentry * root = sb -> s_root ;
590729 struct inode * inode = d_backing_inode (root );
591730 struct superblock_smack * sp = sb -> s_security ;
592731 struct inode_smack * isp ;
593732 struct smack_known * skp ;
594- char * op ;
595- char * commap ;
733+ int i ;
734+ int num_opts = opts -> num_mnt_opts ;
596735 int transmute = 0 ;
597- int specified = 0 ;
598736
599737 if (sp -> smk_initialized )
600738 return 0 ;
601739
602740 sp -> smk_initialized = 1 ;
603741
604- for (op = data ; op != NULL ; op = commap ) {
605- commap = strchr (op , ',' );
606- if (commap != NULL )
607- * commap ++ = '\0' ;
608-
609- if (strncmp (op , SMK_FSHAT , strlen (SMK_FSHAT )) == 0 ) {
610- op += strlen (SMK_FSHAT );
611- skp = smk_import_entry (op , 0 );
742+ for (i = 0 ; i < num_opts ; i ++ ) {
743+ switch (opts -> mnt_opts_flags [i ]) {
744+ case FSDEFAULT_MNT :
745+ skp = smk_import_entry (opts -> mnt_opts [i ], 0 );
612746 if (IS_ERR (skp ))
613747 return PTR_ERR (skp );
614- sp -> smk_hat = skp ;
615- specified = 1 ;
616-
617- } else if (strncmp (op , SMK_FSFLOOR , strlen (SMK_FSFLOOR )) == 0 ) {
618- op += strlen (SMK_FSFLOOR );
619- skp = smk_import_entry (op , 0 );
748+ sp -> smk_default = skp ;
749+ break ;
750+ case FSFLOOR_MNT :
751+ skp = smk_import_entry (opts -> mnt_opts [i ], 0 );
620752 if (IS_ERR (skp ))
621753 return PTR_ERR (skp );
622754 sp -> smk_floor = skp ;
623- specified = 1 ;
624-
625- } else if (strncmp (op , SMK_FSDEFAULT ,
626- strlen (SMK_FSDEFAULT )) == 0 ) {
627- op += strlen (SMK_FSDEFAULT );
628- skp = smk_import_entry (op , 0 );
755+ break ;
756+ case FSHAT_MNT :
757+ skp = smk_import_entry (opts -> mnt_opts [i ], 0 );
629758 if (IS_ERR (skp ))
630759 return PTR_ERR (skp );
631- sp -> smk_default = skp ;
632- specified = 1 ;
633-
634- } else if (strncmp (op , SMK_FSROOT , strlen (SMK_FSROOT )) == 0 ) {
635- op += strlen (SMK_FSROOT );
636- skp = smk_import_entry (op , 0 );
760+ sp -> smk_hat = skp ;
761+ break ;
762+ case FSROOT_MNT :
763+ skp = smk_import_entry (opts -> mnt_opts [i ], 0 );
637764 if (IS_ERR (skp ))
638765 return PTR_ERR (skp );
639766 sp -> smk_root = skp ;
640- specified = 1 ;
641-
642- } else if (strncmp (op , SMK_FSTRANS , strlen (SMK_FSTRANS )) == 0 ) {
643- op += strlen (SMK_FSTRANS );
644- skp = smk_import_entry (op , 0 );
767+ break ;
768+ case FSTRANS_MNT :
769+ skp = smk_import_entry (opts -> mnt_opts [i ], 0 );
645770 if (IS_ERR (skp ))
646771 return PTR_ERR (skp );
647772 sp -> smk_root = skp ;
648773 transmute = 1 ;
649- specified = 1 ;
774+ break ;
775+ default :
776+ break ;
650777 }
651778 }
652779
653780 if (!smack_privileged (CAP_MAC_ADMIN )) {
654781 /*
655782 * Unprivileged mounts don't get to specify Smack values.
656783 */
657- if (specified )
784+ if (num_opts )
658785 return - EPERM ;
659786 /*
660787 * Unprivileged mounts get root and default from the caller.
@@ -663,6 +790,7 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data)
663790 sp -> smk_root = skp ;
664791 sp -> smk_default = skp ;
665792 }
793+
666794 /*
667795 * Initialize the root inode.
668796 */
@@ -681,6 +809,37 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data)
681809 return 0 ;
682810}
683811
812+ /**
813+ * smack_sb_kern_mount - Smack specific mount processing
814+ * @sb: the file system superblock
815+ * @flags: the mount flags
816+ * @data: the smack mount options
817+ *
818+ * Returns 0 on success, an error code on failure
819+ */
820+ static int smack_sb_kern_mount (struct super_block * sb , int flags , void * data )
821+ {
822+ int rc = 0 ;
823+ char * options = data ;
824+ struct security_mnt_opts opts ;
825+
826+ security_init_mnt_opts (& opts );
827+
828+ if (!options )
829+ goto out ;
830+
831+ rc = smack_parse_opts_str (options , & opts );
832+ if (rc )
833+ goto out_err ;
834+
835+ out :
836+ rc = smack_set_mnt_opts (sb , & opts , 0 , NULL );
837+
838+ out_err :
839+ security_free_mnt_opts (& opts );
840+ return rc ;
841+ }
842+
684843/**
685844 * smack_sb_statfs - Smack check on statfs
686845 * @dentry: identifies the file system in question
@@ -4264,6 +4423,8 @@ struct security_hook_list smack_hooks[] = {
42644423 LSM_HOOK_INIT (sb_copy_data , smack_sb_copy_data ),
42654424 LSM_HOOK_INIT (sb_kern_mount , smack_sb_kern_mount ),
42664425 LSM_HOOK_INIT (sb_statfs , smack_sb_statfs ),
4426+ LSM_HOOK_INIT (sb_set_mnt_opts , smack_set_mnt_opts ),
4427+ LSM_HOOK_INIT (sb_parse_opts_str , smack_parse_opts_str ),
42674428
42684429 LSM_HOOK_INIT (bprm_set_creds , smack_bprm_set_creds ),
42694430 LSM_HOOK_INIT (bprm_committing_creds , smack_bprm_committing_creds ),
0 commit comments