smack: pass error code through pointers

This patch makes the following functions to use ERR_PTR() and related
macros to pass the appropriate error code through returned pointers:

smk_parse_smack()
smk_import_entry()
smk_fetch()

It also makes all the other functions that use them to handle the
error cases properly. This ways correct error codes from places
where they happened can be propagated to the user space if necessary.

Doing this it fixes a bug in onlycap and unconfined files
handling. Previously their content was cleared on any error from
smk_import_entry/smk_parse_smack, be it EINVAL (as originally intended)
or ENOMEM. Right now it only reacts on EINVAL passing other codes
properly to userspace.

Comments have been updated accordingly.

Signed-off-by: Lukasz Pawelczyk <l.pawelczyk@samsung.com>
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index 0f410fc..408e20b 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -425,7 +425,7 @@
  * @string: a text string that might be a Smack label
  *
  * Returns a pointer to the entry in the label list that
- * matches the passed string.
+ * matches the passed string or NULL if not found.
  */
 struct smack_known *smk_find_entry(const char *string)
 {
@@ -448,7 +448,7 @@
  * @string: a text string that might contain a Smack label
  * @len: the maximum size, or zero if it is NULL terminated.
  *
- * Returns a pointer to the clean label, or NULL
+ * Returns a pointer to the clean label or an error code.
  */
 char *smk_parse_smack(const char *string, int len)
 {
@@ -464,7 +464,7 @@
 	 * including /smack/cipso and /smack/cipso2
 	 */
 	if (string[0] == '-')
-		return NULL;
+		return ERR_PTR(-EINVAL);
 
 	for (i = 0; i < len; i++)
 		if (string[i] > '~' || string[i] <= ' ' || string[i] == '/' ||
@@ -472,11 +472,13 @@
 			break;
 
 	if (i == 0 || i >= SMK_LONGLABEL)
-		return NULL;
+		return ERR_PTR(-EINVAL);
 
 	smack = kzalloc(i + 1, GFP_KERNEL);
-	if (smack != NULL)
-		strncpy(smack, string, i);
+	if (smack == NULL)
+		return ERR_PTR(-ENOMEM);
+
+	strncpy(smack, string, i);
 
 	return smack;
 }
@@ -523,7 +525,8 @@
  * @len: the maximum size, or zero if it is NULL terminated.
  *
  * Returns a pointer to the entry in the label list that
- * matches the passed string, adding it if necessary.
+ * matches the passed string, adding it if necessary,
+ * or an error code.
  */
 struct smack_known *smk_import_entry(const char *string, int len)
 {
@@ -533,8 +536,8 @@
 	int rc;
 
 	smack = smk_parse_smack(string, len);
-	if (smack == NULL)
-		return NULL;
+	if (IS_ERR(smack))
+		return ERR_CAST(smack);
 
 	mutex_lock(&smack_known_lock);
 
@@ -543,8 +546,10 @@
 		goto freeout;
 
 	skp = kzalloc(sizeof(*skp), GFP_KERNEL);
-	if (skp == NULL)
+	if (skp == NULL) {
+		skp = ERR_PTR(-ENOMEM);
 		goto freeout;
+	}
 
 	skp->smk_known = smack;
 	skp->smk_secid = smack_next_secid++;
@@ -577,7 +582,7 @@
 	 * smk_netlbl_mls failed.
 	 */
 	kfree(skp);
-	skp = NULL;
+	skp = ERR_PTR(rc);
 freeout:
 	kfree(smack);
 unlockout: