diff options
Diffstat (limited to 'security/smack')
-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 9733f8eb1a2a..c21d8c8bf0c7 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 | ||
@@ -789,6 +800,85 @@ static const struct file_operations smk_ambient_ops = { | |||
789 | .write = smk_write_ambient, | 800 | .write = smk_write_ambient, |
790 | }; | 801 | }; |
791 | 802 | ||
803 | /** | ||
804 | * smk_read_onlycap - read() for /smack/onlycap | ||
805 | * @filp: file pointer, not actually used | ||
806 | * @buf: where to put the result | ||
807 | * @cn: maximum to send along | ||
808 | * @ppos: where to start | ||
809 | * | ||
810 | * Returns number of bytes read or error code, as appropriate | ||
811 | */ | ||
812 | static ssize_t smk_read_onlycap(struct file *filp, char __user *buf, | ||
813 | size_t cn, loff_t *ppos) | ||
814 | { | ||
815 | char *smack = ""; | ||
816 | ssize_t rc = -EINVAL; | ||
817 | int asize; | ||
818 | |||
819 | if (*ppos != 0) | ||
820 | return 0; | ||
821 | |||
822 | if (smack_onlycap != NULL) | ||
823 | smack = smack_onlycap; | ||
824 | |||
825 | asize = strlen(smack) + 1; | ||
826 | |||
827 | if (cn >= asize) | ||
828 | rc = simple_read_from_buffer(buf, cn, ppos, smack, asize); | ||
829 | |||
830 | return rc; | ||
831 | } | ||
832 | |||
833 | /** | ||
834 | * smk_write_onlycap - write() for /smack/onlycap | ||
835 | * @filp: file pointer, not actually used | ||
836 | * @buf: where to get the data from | ||
837 | * @count: bytes sent | ||
838 | * @ppos: where to start | ||
839 | * | ||
840 | * Returns number of bytes written or error code, as appropriate | ||
841 | */ | ||
842 | static ssize_t smk_write_onlycap(struct file *file, const char __user *buf, | ||
843 | size_t count, loff_t *ppos) | ||
844 | { | ||
845 | char in[SMK_LABELLEN]; | ||
846 | char *sp = current->security; | ||
847 | |||
848 | if (!capable(CAP_MAC_ADMIN)) | ||
849 | return -EPERM; | ||
850 | |||
851 | /* | ||
852 | * This can be done using smk_access() but is done | ||
853 | * explicitly for clarity. The smk_access() implementation | ||
854 | * would use smk_access(smack_onlycap, MAY_WRITE) | ||
855 | */ | ||
856 | if (smack_onlycap != NULL && smack_onlycap != sp) | ||
857 | return -EPERM; | ||
858 | |||
859 | if (count >= SMK_LABELLEN) | ||
860 | return -EINVAL; | ||
861 | |||
862 | if (copy_from_user(in, buf, count) != 0) | ||
863 | return -EFAULT; | ||
864 | |||
865 | /* | ||
866 | * Should the null string be passed in unset the onlycap value. | ||
867 | * This seems like something to be careful with as usually | ||
868 | * smk_import only expects to return NULL for errors. It | ||
869 | * is usually the case that a nullstring or "\n" would be | ||
870 | * bad to pass to smk_import but in fact this is useful here. | ||
871 | */ | ||
872 | smack_onlycap = smk_import(in, count); | ||
873 | |||
874 | return count; | ||
875 | } | ||
876 | |||
877 | static const struct file_operations smk_onlycap_ops = { | ||
878 | .read = smk_read_onlycap, | ||
879 | .write = smk_write_onlycap, | ||
880 | }; | ||
881 | |||
792 | struct option_names { | 882 | struct option_names { |
793 | int o_number; | 883 | int o_number; |
794 | char *o_name; | 884 | char *o_name; |
@@ -921,6 +1011,8 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent) | |||
921 | {"ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR}, | 1011 | {"ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR}, |
922 | [SMK_NLTYPE] = | 1012 | [SMK_NLTYPE] = |
923 | {"nltype", &smk_nltype_ops, S_IRUGO|S_IWUSR}, | 1013 | {"nltype", &smk_nltype_ops, S_IRUGO|S_IWUSR}, |
1014 | [SMK_ONLYCAP] = | ||
1015 | {"onlycap", &smk_onlycap_ops, S_IRUGO|S_IWUSR}, | ||
924 | /* last one */ {""} | 1016 | /* last one */ {""} |
925 | }; | 1017 | }; |
926 | 1018 | ||