diff options
-rw-r--r-- | security/smack/smack.h | 1 | ||||
-rw-r--r-- | security/smack/smack_access.c | 10 | ||||
-rw-r--r-- | security/smack/smackfs.c | 92 |
3 files changed, 102 insertions, 1 deletions
diff --git a/security/smack/smack.h b/security/smack/smack.h index 4a4477f5afdc..31dce559595a 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h | |||
@@ -178,6 +178,7 @@ u32 smack_to_secid(const char *); | |||
178 | extern int smack_cipso_direct; | 178 | extern int smack_cipso_direct; |
179 | extern int smack_net_nltype; | 179 | extern int smack_net_nltype; |
180 | extern char *smack_net_ambient; | 180 | extern char *smack_net_ambient; |
181 | extern char *smack_onlycap; | ||
181 | 182 | ||
182 | extern struct smack_known *smack_known; | 183 | extern struct smack_known *smack_known; |
183 | extern struct smack_known smack_known_floor; | 184 | extern struct smack_known smack_known_floor; |
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c index f6b5f6eed6dd..79ff21ed4c3b 100644 --- a/security/smack/smack_access.c +++ b/security/smack/smack_access.c | |||
@@ -157,7 +157,7 @@ int smk_access(char *subject_label, char *object_label, int request) | |||
157 | * | 157 | * |
158 | * This function checks the current subject label/object label pair | 158 | * This function checks the current subject label/object label pair |
159 | * in the access rule list and returns 0 if the access is permitted, | 159 | * in the access rule list and returns 0 if the access is permitted, |
160 | * non zero otherwise. It allows that current my have the capability | 160 | * non zero otherwise. It allows that current may have the capability |
161 | * to override the rules. | 161 | * to override the rules. |
162 | */ | 162 | */ |
163 | int smk_curacc(char *obj_label, u32 mode) | 163 | int smk_curacc(char *obj_label, u32 mode) |
@@ -168,6 +168,14 @@ int smk_curacc(char *obj_label, u32 mode) | |||
168 | if (rc == 0) | 168 | if (rc == 0) |
169 | return 0; | 169 | return 0; |
170 | 170 | ||
171 | /* | ||
172 | * Return if a specific label has been designated as the | ||
173 | * only one that gets privilege and current does not | ||
174 | * have that label. | ||
175 | */ | ||
176 | if (smack_onlycap != NULL && smack_onlycap != current->security) | ||
177 | return rc; | ||
178 | |||
171 | if (capable(CAP_MAC_OVERRIDE)) | 179 | if (capable(CAP_MAC_OVERRIDE)) |
172 | return 0; | 180 | return 0; |
173 | 181 | ||
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index 271a835fbbe3..e7c642458ec9 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c | |||
@@ -39,6 +39,7 @@ enum smk_inos { | |||
39 | SMK_DIRECT = 6, /* CIPSO level indicating direct label */ | 39 | SMK_DIRECT = 6, /* CIPSO level indicating direct label */ |
40 | SMK_AMBIENT = 7, /* internet ambient label */ | 40 | SMK_AMBIENT = 7, /* internet ambient label */ |
41 | SMK_NLTYPE = 8, /* label scheme to use by default */ | 41 | SMK_NLTYPE = 8, /* label scheme to use by default */ |
42 | SMK_ONLYCAP = 9, /* the only "capable" label */ | ||
42 | }; | 43 | }; |
43 | 44 | ||
44 | /* | 45 | /* |
@@ -68,6 +69,16 @@ int smack_net_nltype = NETLBL_NLTYPE_CIPSOV4; | |||
68 | */ | 69 | */ |
69 | int smack_cipso_direct = SMACK_CIPSO_DIRECT_DEFAULT; | 70 | int smack_cipso_direct = SMACK_CIPSO_DIRECT_DEFAULT; |
70 | 71 | ||
72 | /* | ||
73 | * Unless a process is running with this label even | ||
74 | * having CAP_MAC_OVERRIDE isn't enough to grant | ||
75 | * privilege to violate MAC policy. If no label is | ||
76 | * designated (the NULL case) capabilities apply to | ||
77 | * everyone. It is expected that the hat (^) label | ||
78 | * will be used if any label is used. | ||
79 | */ | ||
80 | char *smack_onlycap; | ||
81 | |||
71 | static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT; | 82 | static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT; |
72 | struct smk_list_entry *smack_list; | 83 | struct smk_list_entry *smack_list; |
73 | 84 | ||
@@ -787,6 +798,85 @@ static const struct file_operations smk_ambient_ops = { | |||
787 | .write = smk_write_ambient, | 798 | .write = smk_write_ambient, |
788 | }; | 799 | }; |
789 | 800 | ||
801 | /** | ||
802 | * smk_read_onlycap - read() for /smack/onlycap | ||
803 | * @filp: file pointer, not actually used | ||
804 | * @buf: where to put the result | ||
805 | * @cn: maximum to send along | ||
806 | * @ppos: where to start | ||
807 | * | ||
808 | * Returns number of bytes read or error code, as appropriate | ||
809 | */ | ||
810 | static ssize_t smk_read_onlycap(struct file *filp, char __user *buf, | ||
811 | size_t cn, loff_t *ppos) | ||
812 | { | ||
813 | char *smack = ""; | ||
814 | ssize_t rc = -EINVAL; | ||
815 | int asize; | ||
816 | |||
817 | if (*ppos != 0) | ||
818 | return 0; | ||
819 | |||
820 | if (smack_onlycap != NULL) | ||
821 | smack = smack_onlycap; | ||
822 | |||
823 | asize = strlen(smack) + 1; | ||
824 | |||
825 | if (cn >= asize) | ||
826 | rc = simple_read_from_buffer(buf, cn, ppos, smack, asize); | ||
827 | |||
828 | return rc; | ||
829 | } | ||
830 | |||
831 | /** | ||
832 | * smk_write_onlycap - write() for /smack/onlycap | ||
833 | * @filp: file pointer, not actually used | ||
834 | * @buf: where to get the data from | ||
835 | * @count: bytes sent | ||
836 | * @ppos: where to start | ||
837 | * | ||
838 | * Returns number of bytes written or error code, as appropriate | ||
839 | */ | ||
840 | static ssize_t smk_write_onlycap(struct file *file, const char __user *buf, | ||
841 | size_t count, loff_t *ppos) | ||
842 | { | ||
843 | char in[SMK_LABELLEN]; | ||
844 | char *sp = current->security; | ||
845 | |||
846 | if (!capable(CAP_MAC_ADMIN)) | ||
847 | return -EPERM; | ||
848 | |||
849 | /* | ||
850 | * This can be done using smk_access() but is done | ||
851 | * explicitly for clarity. The smk_access() implementation | ||
852 | * would use smk_access(smack_onlycap, MAY_WRITE) | ||
853 | */ | ||
854 | if (smack_onlycap != NULL && smack_onlycap != sp) | ||
855 | return -EPERM; | ||
856 | |||
857 | if (count >= SMK_LABELLEN) | ||
858 | return -EINVAL; | ||
859 | |||
860 | if (copy_from_user(in, buf, count) != 0) | ||
861 | return -EFAULT; | ||
862 | |||
863 | /* | ||
864 | * Should the null string be passed in unset the onlycap value. | ||
865 | * This seems like something to be careful with as usually | ||
866 | * smk_import only expects to return NULL for errors. It | ||
867 | * is usually the case that a nullstring or "\n" would be | ||
868 | * bad to pass to smk_import but in fact this is useful here. | ||
869 | */ | ||
870 | smack_onlycap = smk_import(in, count); | ||
871 | |||
872 | return count; | ||
873 | } | ||
874 | |||
875 | static const struct file_operations smk_onlycap_ops = { | ||
876 | .read = smk_read_onlycap, | ||
877 | .write = smk_write_onlycap, | ||
878 | }; | ||
879 | |||
790 | struct option_names { | 880 | struct option_names { |
791 | int o_number; | 881 | int o_number; |
792 | char *o_name; | 882 | char *o_name; |
@@ -919,6 +1009,8 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent) | |||
919 | {"ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR}, | 1009 | {"ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR}, |
920 | [SMK_NLTYPE] = | 1010 | [SMK_NLTYPE] = |
921 | {"nltype", &smk_nltype_ops, S_IRUGO|S_IWUSR}, | 1011 | {"nltype", &smk_nltype_ops, S_IRUGO|S_IWUSR}, |
1012 | [SMK_ONLYCAP] = | ||
1013 | {"onlycap", &smk_onlycap_ops, S_IRUGO|S_IWUSR}, | ||
922 | /* last one */ {""} | 1014 | /* last one */ {""} |
923 | }; | 1015 | }; |
924 | 1016 | ||