aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/smack/smack.h18
-rw-r--r--security/smack/smack_access.c113
-rw-r--r--security/smack/smack_lsm.c126
-rw-r--r--security/smack/smackfs.c84
4 files changed, 220 insertions, 121 deletions
diff --git a/security/smack/smack.h b/security/smack/smack.h
index 2b6c6a516123..174d3be9aaee 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -41,9 +41,9 @@ struct superblock_smack {
41}; 41};
42 42
43struct socket_smack { 43struct socket_smack {
44 char *smk_out; /* outbound label */ 44 char *smk_out; /* outbound label */
45 char *smk_in; /* inbound label */ 45 char *smk_in; /* inbound label */
46 char smk_packet[SMK_LABELLEN]; /* TCP peer label */ 46 char *smk_packet; /* TCP peer label */
47}; 47};
48 48
49/* 49/*
@@ -116,13 +116,19 @@ struct smk_netlbladdr {
116 * If there is a cipso value associated with the label it 116 * If there is a cipso value associated with the label it
117 * gets stored here, too. This will most likely be rare as 117 * gets stored here, too. This will most likely be rare as
118 * the cipso direct mapping in used internally. 118 * the cipso direct mapping in used internally.
119 *
120 * Keep the access rules for this subject label here so that
121 * the entire set of rules does not need to be examined every
122 * time.
119 */ 123 */
120struct smack_known { 124struct smack_known {
121 struct list_head list; 125 struct list_head list;
122 char smk_known[SMK_LABELLEN]; 126 char smk_known[SMK_LABELLEN];
123 u32 smk_secid; 127 u32 smk_secid;
124 struct smack_cipso *smk_cipso; 128 struct smack_cipso *smk_cipso;
125 spinlock_t smk_cipsolock; /* for changing cipso map */ 129 spinlock_t smk_cipsolock; /* for changing cipso map */
130 struct list_head smk_rules; /* access rules */
131 struct mutex smk_rules_lock; /* lock for the rules */
126}; 132};
127 133
128/* 134/*
@@ -201,10 +207,11 @@ int smk_access_entry(char *, char *, struct list_head *);
201int smk_access(char *, char *, int, struct smk_audit_info *); 207int smk_access(char *, char *, int, struct smk_audit_info *);
202int smk_curacc(char *, u32, struct smk_audit_info *); 208int smk_curacc(char *, u32, struct smk_audit_info *);
203int smack_to_cipso(const char *, struct smack_cipso *); 209int smack_to_cipso(const char *, struct smack_cipso *);
204void smack_from_cipso(u32, char *, char *); 210char *smack_from_cipso(u32, char *);
205char *smack_from_secid(const u32); 211char *smack_from_secid(const u32);
206char *smk_import(const char *, int); 212char *smk_import(const char *, int);
207struct smack_known *smk_import_entry(const char *, int); 213struct smack_known *smk_import_entry(const char *, int);
214struct smack_known *smk_find_entry(const char *);
208u32 smack_to_secid(const char *); 215u32 smack_to_secid(const char *);
209 216
210/* 217/*
@@ -223,7 +230,6 @@ extern struct smack_known smack_known_star;
223extern struct smack_known smack_known_web; 230extern struct smack_known smack_known_web;
224 231
225extern struct list_head smack_known_list; 232extern struct list_head smack_known_list;
226extern struct list_head smack_rule_list;
227extern struct list_head smk_netlbladdr_list; 233extern struct list_head smk_netlbladdr_list;
228 234
229extern struct security_operations smack_ops; 235extern struct security_operations smack_ops;
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index 9637e107f7ea..a885f628f56e 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -77,14 +77,19 @@ int log_policy = SMACK_AUDIT_DENIED;
77 * entry is found returns -ENOENT. 77 * entry is found returns -ENOENT.
78 * 78 *
79 * NOTE: 79 * NOTE:
80 * Even though Smack labels are usually shared on smack_list
81 * labels that come in off the network can't be imported
82 * and added to the list for locking reasons.
83 * 80 *
84 * Therefore, it is necessary to check the contents of the labels, 81 * Earlier versions of this function allowed for labels that
85 * not just the pointer values. Of course, in most cases the labels 82 * were not on the label list. This was done to allow for
86 * will be on the list, so checking the pointers may be a worthwhile 83 * labels to come over the network that had never been seen
87 * optimization. 84 * before on this host. Unless the receiving socket has the
85 * star label this will always result in a failure check. The
86 * star labeled socket case is now handled in the networking
87 * hooks so there is no case where the label is not on the
88 * label list. Checking to see if the address of two labels
89 * is the same is now a reliable test.
90 *
91 * Do the object check first because that is more
92 * likely to differ.
88 */ 93 */
89int smk_access_entry(char *subject_label, char *object_label, 94int smk_access_entry(char *subject_label, char *object_label,
90 struct list_head *rule_list) 95 struct list_head *rule_list)
@@ -93,13 +98,10 @@ int smk_access_entry(char *subject_label, char *object_label,
93 struct smack_rule *srp; 98 struct smack_rule *srp;
94 99
95 list_for_each_entry_rcu(srp, rule_list, list) { 100 list_for_each_entry_rcu(srp, rule_list, list) {
96 if (srp->smk_subject == subject_label || 101 if (srp->smk_object == object_label &&
97 strcmp(srp->smk_subject, subject_label) == 0) { 102 srp->smk_subject == subject_label) {
98 if (srp->smk_object == object_label || 103 may = srp->smk_access;
99 strcmp(srp->smk_object, object_label) == 0) { 104 break;
100 may = srp->smk_access;
101 break;
102 }
103 } 105 }
104 } 106 }
105 107
@@ -117,18 +119,12 @@ int smk_access_entry(char *subject_label, char *object_label,
117 * access rule list and returns 0 if the access is permitted, 119 * access rule list and returns 0 if the access is permitted,
118 * non zero otherwise. 120 * non zero otherwise.
119 * 121 *
120 * Even though Smack labels are usually shared on smack_list 122 * Smack labels are shared on smack_list
121 * labels that come in off the network can't be imported
122 * and added to the list for locking reasons.
123 *
124 * Therefore, it is necessary to check the contents of the labels,
125 * not just the pointer values. Of course, in most cases the labels
126 * will be on the list, so checking the pointers may be a worthwhile
127 * optimization.
128 */ 123 */
129int smk_access(char *subject_label, char *object_label, int request, 124int smk_access(char *subject_label, char *object_label, int request,
130 struct smk_audit_info *a) 125 struct smk_audit_info *a)
131{ 126{
127 struct smack_known *skp;
132 int may = MAY_NOT; 128 int may = MAY_NOT;
133 int rc = 0; 129 int rc = 0;
134 130
@@ -137,8 +133,7 @@ int smk_access(char *subject_label, char *object_label, int request,
137 * 133 *
138 * A star subject can't access any object. 134 * A star subject can't access any object.
139 */ 135 */
140 if (subject_label == smack_known_star.smk_known || 136 if (subject_label == smack_known_star.smk_known) {
141 strcmp(subject_label, smack_known_star.smk_known) == 0) {
142 rc = -EACCES; 137 rc = -EACCES;
143 goto out_audit; 138 goto out_audit;
144 } 139 }
@@ -148,33 +143,27 @@ int smk_access(char *subject_label, char *object_label, int request,
148 * An internet subject can access any object. 143 * An internet subject can access any object.
149 */ 144 */
150 if (object_label == smack_known_web.smk_known || 145 if (object_label == smack_known_web.smk_known ||
151 subject_label == smack_known_web.smk_known || 146 subject_label == smack_known_web.smk_known)
152 strcmp(object_label, smack_known_web.smk_known) == 0 ||
153 strcmp(subject_label, smack_known_web.smk_known) == 0)
154 goto out_audit; 147 goto out_audit;
155 /* 148 /*
156 * A star object can be accessed by any subject. 149 * A star object can be accessed by any subject.
157 */ 150 */
158 if (object_label == smack_known_star.smk_known || 151 if (object_label == smack_known_star.smk_known)
159 strcmp(object_label, smack_known_star.smk_known) == 0)
160 goto out_audit; 152 goto out_audit;
161 /* 153 /*
162 * An object can be accessed in any way by a subject 154 * An object can be accessed in any way by a subject
163 * with the same label. 155 * with the same label.
164 */ 156 */
165 if (subject_label == object_label || 157 if (subject_label == object_label)
166 strcmp(subject_label, object_label) == 0)
167 goto out_audit; 158 goto out_audit;
168 /* 159 /*
169 * A hat subject can read any object. 160 * A hat subject can read any object.
170 * A floor object can be read by any subject. 161 * A floor object can be read by any subject.
171 */ 162 */
172 if ((request & MAY_ANYREAD) == request) { 163 if ((request & MAY_ANYREAD) == request) {
173 if (object_label == smack_known_floor.smk_known || 164 if (object_label == smack_known_floor.smk_known)
174 strcmp(object_label, smack_known_floor.smk_known) == 0)
175 goto out_audit; 165 goto out_audit;
176 if (subject_label == smack_known_hat.smk_known || 166 if (subject_label == smack_known_hat.smk_known)
177 strcmp(subject_label, smack_known_hat.smk_known) == 0)
178 goto out_audit; 167 goto out_audit;
179 } 168 }
180 /* 169 /*
@@ -184,8 +173,9 @@ int smk_access(char *subject_label, char *object_label, int request,
184 * good. A negative response from smk_access_entry() 173 * good. A negative response from smk_access_entry()
185 * indicates there is no entry for this pair. 174 * indicates there is no entry for this pair.
186 */ 175 */
176 skp = smk_find_entry(subject_label);
187 rcu_read_lock(); 177 rcu_read_lock();
188 may = smk_access_entry(subject_label, object_label, &smack_rule_list); 178 may = smk_access_entry(subject_label, object_label, &skp->smk_rules);
189 rcu_read_unlock(); 179 rcu_read_unlock();
190 180
191 if (may > 0 && (request & may) == request) 181 if (may > 0 && (request & may) == request)
@@ -344,6 +334,25 @@ void smack_log(char *subject_label, char *object_label, int request,
344static DEFINE_MUTEX(smack_known_lock); 334static DEFINE_MUTEX(smack_known_lock);
345 335
346/** 336/**
337 * smk_find_entry - find a label on the list, return the list entry
338 * @string: a text string that might be a Smack label
339 *
340 * Returns a pointer to the entry in the label list that
341 * matches the passed string.
342 */
343struct smack_known *smk_find_entry(const char *string)
344{
345 struct smack_known *skp;
346
347 list_for_each_entry_rcu(skp, &smack_known_list, list) {
348 if (strncmp(skp->smk_known, string, SMK_MAXLEN) == 0)
349 return skp;
350 }
351
352 return NULL;
353}
354
355/**
347 * smk_import_entry - import a label, return the list entry 356 * smk_import_entry - import a label, return the list entry
348 * @string: a text string that might be a Smack label 357 * @string: a text string that might be a Smack label
349 * @len: the maximum size, or zero if it is NULL terminated. 358 * @len: the maximum size, or zero if it is NULL terminated.
@@ -378,21 +387,17 @@ struct smack_known *smk_import_entry(const char *string, int len)
378 387
379 mutex_lock(&smack_known_lock); 388 mutex_lock(&smack_known_lock);
380 389
381 found = 0; 390 skp = smk_find_entry(smack);
382 list_for_each_entry_rcu(skp, &smack_known_list, list) {
383 if (strncmp(skp->smk_known, smack, SMK_MAXLEN) == 0) {
384 found = 1;
385 break;
386 }
387 }
388 391
389 if (found == 0) { 392 if (skp == NULL) {
390 skp = kzalloc(sizeof(struct smack_known), GFP_KERNEL); 393 skp = kzalloc(sizeof(struct smack_known), GFP_KERNEL);
391 if (skp != NULL) { 394 if (skp != NULL) {
392 strncpy(skp->smk_known, smack, SMK_MAXLEN); 395 strncpy(skp->smk_known, smack, SMK_MAXLEN);
393 skp->smk_secid = smack_next_secid++; 396 skp->smk_secid = smack_next_secid++;
394 skp->smk_cipso = NULL; 397 skp->smk_cipso = NULL;
398 INIT_LIST_HEAD(&skp->smk_rules);
395 spin_lock_init(&skp->smk_cipsolock); 399 spin_lock_init(&skp->smk_cipsolock);
400 mutex_init(&skp->smk_rules_lock);
396 /* 401 /*
397 * Make sure that the entry is actually 402 * Make sure that the entry is actually
398 * filled before putting it on the list. 403 * filled before putting it on the list.
@@ -480,19 +485,12 @@ u32 smack_to_secid(const char *smack)
480 * smack_from_cipso - find the Smack label associated with a CIPSO option 485 * smack_from_cipso - find the Smack label associated with a CIPSO option
481 * @level: Bell & LaPadula level from the network 486 * @level: Bell & LaPadula level from the network
482 * @cp: Bell & LaPadula categories from the network 487 * @cp: Bell & LaPadula categories from the network
483 * @result: where to put the Smack value
484 * 488 *
485 * This is a simple lookup in the label table. 489 * This is a simple lookup in the label table.
486 * 490 *
487 * This is an odd duck as far as smack handling goes in that 491 * Return the matching label from the label list or NULL.
488 * it sends back a copy of the smack label rather than a pointer
489 * to the master list. This is done because it is possible for
490 * a foreign host to send a smack label that is new to this
491 * machine and hence not on the list. That would not be an
492 * issue except that adding an entry to the master list can't
493 * be done at that point.
494 */ 492 */
495void smack_from_cipso(u32 level, char *cp, char *result) 493char *smack_from_cipso(u32 level, char *cp)
496{ 494{
497 struct smack_known *kp; 495 struct smack_known *kp;
498 char *final = NULL; 496 char *final = NULL;
@@ -509,12 +507,13 @@ void smack_from_cipso(u32 level, char *cp, char *result)
509 final = kp->smk_known; 507 final = kp->smk_known;
510 508
511 spin_unlock_bh(&kp->smk_cipsolock); 509 spin_unlock_bh(&kp->smk_cipsolock);
510
511 if (final != NULL)
512 break;
512 } 513 }
513 rcu_read_unlock(); 514 rcu_read_unlock();
514 if (final == NULL) 515
515 final = smack_known_huh.smk_known; 516 return final;
516 strncpy(result, final, SMK_MAXLEN);
517 return;
518} 517}
519 518
520/** 519/**
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index b9c5e149903b..fb915163f967 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -516,6 +516,8 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
516 const struct qstr *qstr, char **name, 516 const struct qstr *qstr, char **name,
517 void **value, size_t *len) 517 void **value, size_t *len)
518{ 518{
519 struct smack_known *skp;
520 char *csp = smk_of_current();
519 char *isp = smk_of_inode(inode); 521 char *isp = smk_of_inode(inode);
520 char *dsp = smk_of_inode(dir); 522 char *dsp = smk_of_inode(dir);
521 int may; 523 int may;
@@ -527,8 +529,9 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
527 } 529 }
528 530
529 if (value) { 531 if (value) {
532 skp = smk_find_entry(csp);
530 rcu_read_lock(); 533 rcu_read_lock();
531 may = smk_access_entry(smk_of_current(), dsp, &smack_rule_list); 534 may = smk_access_entry(csp, dsp, &skp->smk_rules);
532 rcu_read_unlock(); 535 rcu_read_unlock();
533 536
534 /* 537 /*
@@ -1138,6 +1141,7 @@ static int smack_file_mmap(struct file *file,
1138 unsigned long flags, unsigned long addr, 1141 unsigned long flags, unsigned long addr,
1139 unsigned long addr_only) 1142 unsigned long addr_only)
1140{ 1143{
1144 struct smack_known *skp;
1141 struct smack_rule *srp; 1145 struct smack_rule *srp;
1142 struct task_smack *tsp; 1146 struct task_smack *tsp;
1143 char *sp; 1147 char *sp;
@@ -1170,6 +1174,7 @@ static int smack_file_mmap(struct file *file,
1170 1174
1171 tsp = current_security(); 1175 tsp = current_security();
1172 sp = smk_of_current(); 1176 sp = smk_of_current();
1177 skp = smk_find_entry(sp);
1173 rc = 0; 1178 rc = 0;
1174 1179
1175 rcu_read_lock(); 1180 rcu_read_lock();
@@ -1177,15 +1182,8 @@ static int smack_file_mmap(struct file *file,
1177 * For each Smack rule associated with the subject 1182 * For each Smack rule associated with the subject
1178 * label verify that the SMACK64MMAP also has access 1183 * label verify that the SMACK64MMAP also has access
1179 * to that rule's object label. 1184 * to that rule's object label.
1180 *
1181 * Because neither of the labels comes
1182 * from the networking code it is sufficient
1183 * to compare pointers.
1184 */ 1185 */
1185 list_for_each_entry_rcu(srp, &smack_rule_list, list) { 1186 list_for_each_entry_rcu(srp, &skp->smk_rules, list) {
1186 if (srp->smk_subject != sp)
1187 continue;
1188
1189 osmack = srp->smk_object; 1187 osmack = srp->smk_object;
1190 /* 1188 /*
1191 * Matching labels always allows access. 1189 * Matching labels always allows access.
@@ -1214,7 +1212,8 @@ static int smack_file_mmap(struct file *file,
1214 * If there isn't one a SMACK64MMAP subject 1212 * If there isn't one a SMACK64MMAP subject
1215 * can't have as much access as current. 1213 * can't have as much access as current.
1216 */ 1214 */
1217 mmay = smk_access_entry(msmack, osmack, &smack_rule_list); 1215 skp = smk_find_entry(msmack);
1216 mmay = smk_access_entry(msmack, osmack, &skp->smk_rules);
1218 if (mmay == -ENOENT) { 1217 if (mmay == -ENOENT) {
1219 rc = -EACCES; 1218 rc = -EACCES;
1220 break; 1219 break;
@@ -1711,7 +1710,7 @@ static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags)
1711 1710
1712 ssp->smk_in = csp; 1711 ssp->smk_in = csp;
1713 ssp->smk_out = csp; 1712 ssp->smk_out = csp;
1714 ssp->smk_packet[0] = '\0'; 1713 ssp->smk_packet = NULL;
1715 1714
1716 sk->sk_security = ssp; 1715 sk->sk_security = ssp;
1717 1716
@@ -2813,16 +2812,17 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg,
2813 return smack_netlabel_send(sock->sk, sip); 2812 return smack_netlabel_send(sock->sk, sip);
2814} 2813}
2815 2814
2816
2817/** 2815/**
2818 * smack_from_secattr - Convert a netlabel attr.mls.lvl/attr.mls.cat pair to smack 2816 * smack_from_secattr - Convert a netlabel attr.mls.lvl/attr.mls.cat pair to smack
2819 * @sap: netlabel secattr 2817 * @sap: netlabel secattr
2820 * @sip: where to put the result 2818 * @ssp: socket security information
2821 * 2819 *
2822 * Copies a smack label into sip 2820 * Returns a pointer to a Smack label found on the label list.
2823 */ 2821 */
2824static void smack_from_secattr(struct netlbl_lsm_secattr *sap, char *sip) 2822static char *smack_from_secattr(struct netlbl_lsm_secattr *sap,
2823 struct socket_smack *ssp)
2825{ 2824{
2825 struct smack_known *skp;
2826 char smack[SMK_LABELLEN]; 2826 char smack[SMK_LABELLEN];
2827 char *sp; 2827 char *sp;
2828 int pcat; 2828 int pcat;
@@ -2852,15 +2852,43 @@ static void smack_from_secattr(struct netlbl_lsm_secattr *sap, char *sip)
2852 * we are already done. WeeHee. 2852 * we are already done. WeeHee.
2853 */ 2853 */
2854 if (sap->attr.mls.lvl == smack_cipso_direct) { 2854 if (sap->attr.mls.lvl == smack_cipso_direct) {
2855 memcpy(sip, smack, SMK_MAXLEN); 2855 /*
2856 return; 2856 * The label sent is usually on the label list.
2857 *
2858 * If it is not we may still want to allow the
2859 * delivery.
2860 *
2861 * If the recipient is accepting all packets
2862 * because it is using the star ("*") label
2863 * for SMACK64IPIN provide the web ("@") label
2864 * so that a directed response will succeed.
2865 * This is not very correct from a MAC point
2866 * of view, but gets around the problem that
2867 * locking prevents adding the newly discovered
2868 * label to the list.
2869 * The case where the recipient is not using
2870 * the star label should obviously fail.
2871 * The easy way to do this is to provide the
2872 * star label as the subject label.
2873 */
2874 skp = smk_find_entry(smack);
2875 if (skp != NULL)
2876 return skp->smk_known;
2877 if (ssp != NULL &&
2878 ssp->smk_in == smack_known_star.smk_known)
2879 return smack_known_web.smk_known;
2880 return smack_known_star.smk_known;
2857 } 2881 }
2858 /* 2882 /*
2859 * Look it up in the supplied table if it is not 2883 * Look it up in the supplied table if it is not
2860 * a direct mapping. 2884 * a direct mapping.
2861 */ 2885 */
2862 smack_from_cipso(sap->attr.mls.lvl, smack, sip); 2886 sp = smack_from_cipso(sap->attr.mls.lvl, smack);
2863 return; 2887 if (sp != NULL)
2888 return sp;
2889 if (ssp != NULL && ssp->smk_in == smack_known_star.smk_known)
2890 return smack_known_web.smk_known;
2891 return smack_known_star.smk_known;
2864 } 2892 }
2865 if ((sap->flags & NETLBL_SECATTR_SECID) != 0) { 2893 if ((sap->flags & NETLBL_SECATTR_SECID) != 0) {
2866 /* 2894 /*
@@ -2875,16 +2903,14 @@ static void smack_from_secattr(struct netlbl_lsm_secattr *sap, char *sip)
2875 * secid is from a fallback. 2903 * secid is from a fallback.
2876 */ 2904 */
2877 BUG_ON(sp == NULL); 2905 BUG_ON(sp == NULL);
2878 strncpy(sip, sp, SMK_MAXLEN); 2906 return sp;
2879 return;
2880 } 2907 }
2881 /* 2908 /*
2882 * Without guidance regarding the smack value 2909 * Without guidance regarding the smack value
2883 * for the packet fall back on the network 2910 * for the packet fall back on the network
2884 * ambient value. 2911 * ambient value.
2885 */ 2912 */
2886 strncpy(sip, smack_net_ambient, SMK_MAXLEN); 2913 return smack_net_ambient;
2887 return;
2888} 2914}
2889 2915
2890/** 2916/**
@@ -2898,7 +2924,6 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
2898{ 2924{
2899 struct netlbl_lsm_secattr secattr; 2925 struct netlbl_lsm_secattr secattr;
2900 struct socket_smack *ssp = sk->sk_security; 2926 struct socket_smack *ssp = sk->sk_security;
2901 char smack[SMK_LABELLEN];
2902 char *csp; 2927 char *csp;
2903 int rc; 2928 int rc;
2904 struct smk_audit_info ad; 2929 struct smk_audit_info ad;
@@ -2911,10 +2936,9 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
2911 netlbl_secattr_init(&secattr); 2936 netlbl_secattr_init(&secattr);
2912 2937
2913 rc = netlbl_skbuff_getattr(skb, sk->sk_family, &secattr); 2938 rc = netlbl_skbuff_getattr(skb, sk->sk_family, &secattr);
2914 if (rc == 0) { 2939 if (rc == 0)
2915 smack_from_secattr(&secattr, smack); 2940 csp = smack_from_secattr(&secattr, ssp);
2916 csp = smack; 2941 else
2917 } else
2918 csp = smack_net_ambient; 2942 csp = smack_net_ambient;
2919 2943
2920 netlbl_secattr_destroy(&secattr); 2944 netlbl_secattr_destroy(&secattr);
@@ -2951,15 +2975,19 @@ static int smack_socket_getpeersec_stream(struct socket *sock,
2951 int __user *optlen, unsigned len) 2975 int __user *optlen, unsigned len)
2952{ 2976{
2953 struct socket_smack *ssp; 2977 struct socket_smack *ssp;
2954 int slen; 2978 char *rcp = "";
2979 int slen = 1;
2955 int rc = 0; 2980 int rc = 0;
2956 2981
2957 ssp = sock->sk->sk_security; 2982 ssp = sock->sk->sk_security;
2958 slen = strlen(ssp->smk_packet) + 1; 2983 if (ssp->smk_packet != NULL) {
2984 rcp = ssp->smk_packet;
2985 slen = strlen(rcp) + 1;
2986 }
2959 2987
2960 if (slen > len) 2988 if (slen > len)
2961 rc = -ERANGE; 2989 rc = -ERANGE;
2962 else if (copy_to_user(optval, ssp->smk_packet, slen) != 0) 2990 else if (copy_to_user(optval, rcp, slen) != 0)
2963 rc = -EFAULT; 2991 rc = -EFAULT;
2964 2992
2965 if (put_user(slen, optlen) != 0) 2993 if (put_user(slen, optlen) != 0)
@@ -2982,8 +3010,8 @@ static int smack_socket_getpeersec_dgram(struct socket *sock,
2982 3010
2983{ 3011{
2984 struct netlbl_lsm_secattr secattr; 3012 struct netlbl_lsm_secattr secattr;
2985 struct socket_smack *sp; 3013 struct socket_smack *ssp = NULL;
2986 char smack[SMK_LABELLEN]; 3014 char *sp;
2987 int family = PF_UNSPEC; 3015 int family = PF_UNSPEC;
2988 u32 s = 0; /* 0 is the invalid secid */ 3016 u32 s = 0; /* 0 is the invalid secid */
2989 int rc; 3017 int rc;
@@ -2998,17 +3026,19 @@ static int smack_socket_getpeersec_dgram(struct socket *sock,
2998 family = sock->sk->sk_family; 3026 family = sock->sk->sk_family;
2999 3027
3000 if (family == PF_UNIX) { 3028 if (family == PF_UNIX) {
3001 sp = sock->sk->sk_security; 3029 ssp = sock->sk->sk_security;
3002 s = smack_to_secid(sp->smk_out); 3030 s = smack_to_secid(ssp->smk_out);
3003 } else if (family == PF_INET || family == PF_INET6) { 3031 } else if (family == PF_INET || family == PF_INET6) {
3004 /* 3032 /*
3005 * Translate what netlabel gave us. 3033 * Translate what netlabel gave us.
3006 */ 3034 */
3035 if (sock != NULL && sock->sk != NULL)
3036 ssp = sock->sk->sk_security;
3007 netlbl_secattr_init(&secattr); 3037 netlbl_secattr_init(&secattr);
3008 rc = netlbl_skbuff_getattr(skb, family, &secattr); 3038 rc = netlbl_skbuff_getattr(skb, family, &secattr);
3009 if (rc == 0) { 3039 if (rc == 0) {
3010 smack_from_secattr(&secattr, smack); 3040 sp = smack_from_secattr(&secattr, ssp);
3011 s = smack_to_secid(smack); 3041 s = smack_to_secid(sp);
3012 } 3042 }
3013 netlbl_secattr_destroy(&secattr); 3043 netlbl_secattr_destroy(&secattr);
3014 } 3044 }
@@ -3056,7 +3086,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
3056 struct netlbl_lsm_secattr secattr; 3086 struct netlbl_lsm_secattr secattr;
3057 struct sockaddr_in addr; 3087 struct sockaddr_in addr;
3058 struct iphdr *hdr; 3088 struct iphdr *hdr;
3059 char smack[SMK_LABELLEN]; 3089 char *sp;
3060 int rc; 3090 int rc;
3061 struct smk_audit_info ad; 3091 struct smk_audit_info ad;
3062 3092
@@ -3067,9 +3097,9 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
3067 netlbl_secattr_init(&secattr); 3097 netlbl_secattr_init(&secattr);
3068 rc = netlbl_skbuff_getattr(skb, family, &secattr); 3098 rc = netlbl_skbuff_getattr(skb, family, &secattr);
3069 if (rc == 0) 3099 if (rc == 0)
3070 smack_from_secattr(&secattr, smack); 3100 sp = smack_from_secattr(&secattr, ssp);
3071 else 3101 else
3072 strncpy(smack, smack_known_huh.smk_known, SMK_MAXLEN); 3102 sp = smack_known_huh.smk_known;
3073 netlbl_secattr_destroy(&secattr); 3103 netlbl_secattr_destroy(&secattr);
3074 3104
3075#ifdef CONFIG_AUDIT 3105#ifdef CONFIG_AUDIT
@@ -3082,7 +3112,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
3082 * Receiving a packet requires that the other end be able to write 3112 * Receiving a packet requires that the other end be able to write
3083 * here. Read access is not required. 3113 * here. Read access is not required.
3084 */ 3114 */
3085 rc = smk_access(smack, ssp->smk_in, MAY_WRITE, &ad); 3115 rc = smk_access(sp, ssp->smk_in, MAY_WRITE, &ad);
3086 if (rc != 0) 3116 if (rc != 0)
3087 return rc; 3117 return rc;
3088 3118
@@ -3090,7 +3120,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
3090 * Save the peer's label in the request_sock so we can later setup 3120 * Save the peer's label in the request_sock so we can later setup
3091 * smk_packet in the child socket so that SO_PEERCRED can report it. 3121 * smk_packet in the child socket so that SO_PEERCRED can report it.
3092 */ 3122 */
3093 req->peer_secid = smack_to_secid(smack); 3123 req->peer_secid = smack_to_secid(sp);
3094 3124
3095 /* 3125 /*
3096 * We need to decide if we want to label the incoming connection here 3126 * We need to decide if we want to label the incoming connection here
@@ -3103,7 +3133,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
3103 if (smack_host_label(&addr) == NULL) { 3133 if (smack_host_label(&addr) == NULL) {
3104 rcu_read_unlock(); 3134 rcu_read_unlock();
3105 netlbl_secattr_init(&secattr); 3135 netlbl_secattr_init(&secattr);
3106 smack_to_secattr(smack, &secattr); 3136 smack_to_secattr(sp, &secattr);
3107 rc = netlbl_req_setattr(req, &secattr); 3137 rc = netlbl_req_setattr(req, &secattr);
3108 netlbl_secattr_destroy(&secattr); 3138 netlbl_secattr_destroy(&secattr);
3109 } else { 3139 } else {
@@ -3125,13 +3155,11 @@ static void smack_inet_csk_clone(struct sock *sk,
3125 const struct request_sock *req) 3155 const struct request_sock *req)
3126{ 3156{
3127 struct socket_smack *ssp = sk->sk_security; 3157 struct socket_smack *ssp = sk->sk_security;
3128 char *smack;
3129 3158
3130 if (req->peer_secid != 0) { 3159 if (req->peer_secid != 0)
3131 smack = smack_from_secid(req->peer_secid); 3160 ssp->smk_packet = smack_from_secid(req->peer_secid);
3132 strncpy(ssp->smk_packet, smack, SMK_MAXLEN); 3161 else
3133 } else 3162 ssp->smk_packet = NULL;
3134 ssp->smk_packet[0] = '\0';
3135} 3163}
3136 3164
3137/* 3165/*
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index f4c28eeba1b1..76e520be1b5d 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -86,6 +86,16 @@ char *smack_onlycap;
86 */ 86 */
87 87
88LIST_HEAD(smk_netlbladdr_list); 88LIST_HEAD(smk_netlbladdr_list);
89
90/*
91 * Rule lists are maintained for each label.
92 * This master list is just for reading /smack/load.
93 */
94struct smack_master_list {
95 struct list_head list;
96 struct smack_rule *smk_rule;
97};
98
89LIST_HEAD(smack_rule_list); 99LIST_HEAD(smack_rule_list);
90 100
91static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT; 101static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT;
@@ -93,7 +103,10 @@ static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT;
93const char *smack_cipso_option = SMACK_CIPSO_OPTION; 103const char *smack_cipso_option = SMACK_CIPSO_OPTION;
94 104
95 105
106#define SEQ_READ_FINISHED ((loff_t)-1)
107/*
96#define SEQ_READ_FINISHED 1 108#define SEQ_READ_FINISHED 1
109*/
97 110
98/* 111/*
99 * Values for parsing cipso rules 112 * Values for parsing cipso rules
@@ -160,9 +173,13 @@ static int smk_set_access(struct smack_rule *srp, struct list_head *rule_list,
160 173
161 mutex_lock(rule_lock); 174 mutex_lock(rule_lock);
162 175
176 /*
177 * Because the object label is less likely to match
178 * than the subject label check it first
179 */
163 list_for_each_entry_rcu(sp, rule_list, list) { 180 list_for_each_entry_rcu(sp, rule_list, list) {
164 if (sp->smk_subject == srp->smk_subject && 181 if (sp->smk_object == srp->smk_object &&
165 sp->smk_object == srp->smk_object) { 182 sp->smk_subject == srp->smk_subject) {
166 found = 1; 183 found = 1;
167 sp->smk_access = srp->smk_access; 184 sp->smk_access = srp->smk_access;
168 break; 185 break;
@@ -273,9 +290,12 @@ static ssize_t smk_write_load_list(struct file *file, const char __user *buf,
273 struct list_head *rule_list, 290 struct list_head *rule_list,
274 struct mutex *rule_lock) 291 struct mutex *rule_lock)
275{ 292{
293 struct smack_master_list *smlp;
294 struct smack_known *skp;
276 struct smack_rule *rule; 295 struct smack_rule *rule;
277 char *data; 296 char *data;
278 int rc = -EINVAL; 297 int rc = -EINVAL;
298 int load = 0;
279 299
280 /* 300 /*
281 * No partial writes. 301 * No partial writes.
@@ -313,13 +333,27 @@ static ssize_t smk_write_load_list(struct file *file, const char __user *buf,
313 if (smk_parse_rule(data, rule)) 333 if (smk_parse_rule(data, rule))
314 goto out_free_rule; 334 goto out_free_rule;
315 335
336 if (rule_list == NULL) {
337 load = 1;
338 skp = smk_find_entry(rule->smk_subject);
339 rule_list = &skp->smk_rules;
340 rule_lock = &skp->smk_rules_lock;
341 }
342
316 rc = count; 343 rc = count;
317 /* 344 /*
318 * smk_set_access returns true if there was already a rule 345 * smk_set_access returns true if there was already a rule
319 * for the subject/object pair, and false if it was new. 346 * for the subject/object pair, and false if it was new.
320 */ 347 */
321 if (!smk_set_access(rule, rule_list, rule_lock)) 348 if (!smk_set_access(rule, rule_list, rule_lock)) {
349 smlp = kzalloc(sizeof(*smlp), GFP_KERNEL);
350 if (smlp != NULL) {
351 smlp->smk_rule = rule;
352 list_add_rcu(&smlp->list, &smack_rule_list);
353 } else
354 rc = -ENOMEM;
322 goto out; 355 goto out;
356 }
323 357
324out_free_rule: 358out_free_rule:
325 kfree(rule); 359 kfree(rule);
@@ -335,11 +369,24 @@ out:
335 369
336static void *load_seq_start(struct seq_file *s, loff_t *pos) 370static void *load_seq_start(struct seq_file *s, loff_t *pos)
337{ 371{
338 if (*pos == SEQ_READ_FINISHED) 372 struct list_head *list;
373
374 /*
375 * This is 0 the first time through.
376 */
377 if (s->index == 0)
378 s->private = &smack_rule_list;
379
380 if (s->private == NULL)
339 return NULL; 381 return NULL;
340 if (list_empty(&smack_rule_list)) 382
383 list = s->private;
384 if (list_empty(list))
341 return NULL; 385 return NULL;
342 return smack_rule_list.next; 386
387 if (s->index == 0)
388 return list->next;
389 return list;
343} 390}
344 391
345static void *load_seq_next(struct seq_file *s, void *v, loff_t *pos) 392static void *load_seq_next(struct seq_file *s, void *v, loff_t *pos)
@@ -347,17 +394,19 @@ static void *load_seq_next(struct seq_file *s, void *v, loff_t *pos)
347 struct list_head *list = v; 394 struct list_head *list = v;
348 395
349 if (list_is_last(list, &smack_rule_list)) { 396 if (list_is_last(list, &smack_rule_list)) {
350 *pos = SEQ_READ_FINISHED; 397 s->private = NULL;
351 return NULL; 398 return NULL;
352 } 399 }
400 s->private = list->next;
353 return list->next; 401 return list->next;
354} 402}
355 403
356static int load_seq_show(struct seq_file *s, void *v) 404static int load_seq_show(struct seq_file *s, void *v)
357{ 405{
358 struct list_head *list = v; 406 struct list_head *list = v;
359 struct smack_rule *srp = 407 struct smack_master_list *smlp =
360 list_entry(list, struct smack_rule, list); 408 list_entry(list, struct smack_master_list, list);
409 struct smack_rule *srp = smlp->smk_rule;
361 410
362 seq_printf(s, "%s %s", (char *)srp->smk_subject, 411 seq_printf(s, "%s %s", (char *)srp->smk_subject,
363 (char *)srp->smk_object); 412 (char *)srp->smk_object);
@@ -426,8 +475,11 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf,
426 if (!capable(CAP_MAC_ADMIN)) 475 if (!capable(CAP_MAC_ADMIN))
427 return -EPERM; 476 return -EPERM;
428 477
478/*
429 return smk_write_load_list(file, buf, count, ppos, &smack_rule_list, 479 return smk_write_load_list(file, buf, count, ppos, &smack_rule_list,
430 &smack_list_lock); 480 &smack_list_lock);
481*/
482 return smk_write_load_list(file, buf, count, ppos, NULL, NULL);
431} 483}
432 484
433static const struct file_operations smk_load_ops = { 485static const struct file_operations smk_load_ops = {
@@ -1588,6 +1640,20 @@ static int __init init_smk_fs(void)
1588 smk_cipso_doi(); 1640 smk_cipso_doi();
1589 smk_unlbl_ambient(NULL); 1641 smk_unlbl_ambient(NULL);
1590 1642
1643 mutex_init(&smack_known_floor.smk_rules_lock);
1644 mutex_init(&smack_known_hat.smk_rules_lock);
1645 mutex_init(&smack_known_huh.smk_rules_lock);
1646 mutex_init(&smack_known_invalid.smk_rules_lock);
1647 mutex_init(&smack_known_star.smk_rules_lock);
1648 mutex_init(&smack_known_web.smk_rules_lock);
1649
1650 INIT_LIST_HEAD(&smack_known_floor.smk_rules);
1651 INIT_LIST_HEAD(&smack_known_hat.smk_rules);
1652 INIT_LIST_HEAD(&smack_known_huh.smk_rules);
1653 INIT_LIST_HEAD(&smack_known_invalid.smk_rules);
1654 INIT_LIST_HEAD(&smack_known_star.smk_rules);
1655 INIT_LIST_HEAD(&smack_known_web.smk_rules);
1656
1591 return err; 1657 return err;
1592} 1658}
1593 1659