#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/errno.h>
+#include "sidtab.h"
 #include "mls.h"
 #include "policydb.h"
 #include "services.h"
        return 1;
 }
 
+/*
+ * Copies the MLS range from `src' into `dst'.
+ */
+static inline int mls_copy_context(struct context *dst,
+                                  struct context *src)
+{
+       int l, rc = 0;
+
+       /* Copy the MLS range from the source context */
+       for (l = 0; l < 2; l++) {
+               dst->range.level[l].sens = src->range.level[l].sens;
+               rc = ebitmap_cpy(&dst->range.level[l].cat,
+                                &src->range.level[l].cat);
+               if (rc)
+                       break;
+       }
+
+       return rc;
+}
+
 /*
  * Set the MLS fields in the security context structure
  * `context' based on the string representation in
  *
  * This function modifies the string in place, inserting
  * NULL characters to terminate the MLS fields.
+ *
+ * If a def_sid is provided and no MLS field is present,
+ * copy the MLS field of the associated default context.
+ * Used for upgraded to MLS systems where objects may lack
+ * MLS fields.
+ *
+ * Policy read-lock must be held for sidtab lookup.
+ *
  */
 int mls_context_to_sid(char oldc,
                       char **scontext,
-                      struct context *context)
+                      struct context *context,
+                      struct sidtab *s,
+                      u32 def_sid)
 {
 
        char delim;
        if (!selinux_mls_enabled)
                return 0;
 
-       /* No MLS component to the security context. */
-       if (!oldc)
+       /*
+        * No MLS component to the security context, try and map to
+        * default if provided.
+        */
+       if (!oldc) {
+               struct context *defcon;
+
+               if (def_sid == SECSID_NULL)
+                       goto out;
+
+               defcon = sidtab_search(s, def_sid);
+               if (!defcon)
+                       goto out;
+
+               rc = mls_copy_context(context, defcon);
                goto out;
+       }
 
        /* Extract low sensitivity. */
        scontextp = p = *scontext;
        return rc;
 }
 
-/*
- * Copies the MLS range from `src' into `dst'.
- */
-static inline int mls_copy_context(struct context *dst,
-                                  struct context *src)
-{
-       int l, rc = 0;
-
-       /* Copy the MLS range from the source context */
-       for (l = 0; l < 2; l++) {
-               dst->range.level[l].sens = src->range.level[l].sens;
-               rc = ebitmap_cpy(&dst->range.level[l].cat,
-                                &src->range.level[l].cat);
-               if (rc)
-                       break;
-       }
-
-       return rc;
-}
-
 /*
  * Copies the effective MLS range from `src' into `dst'.
  */
 
 
 }
 
-/**
- * security_context_to_sid - Obtain a SID for a given security context.
- * @scontext: security context
- * @scontext_len: length in bytes
- * @sid: security identifier, SID
- *
- * Obtains a SID associated with the security context that
- * has the string representation specified by @scontext.
- * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient
- * memory is available, or 0 on success.
- */
-int security_context_to_sid(char *scontext, u32 scontext_len, u32 *sid)
+static int security_context_to_sid_core(char *scontext, u32 scontext_len, u32 *sid, u32 def_sid)
 {
        char *scontext2;
        struct context context;
 
        context.type = typdatum->value;
 
-       rc = mls_context_to_sid(oldc, &p, &context);
+       rc = mls_context_to_sid(oldc, &p, &context, &sidtab, def_sid);
        if (rc)
                goto out_unlock;
 
        return rc;
 }
 
+/**
+ * security_context_to_sid - Obtain a SID for a given security context.
+ * @scontext: security context
+ * @scontext_len: length in bytes
+ * @sid: security identifier, SID
+ *
+ * Obtains a SID associated with the security context that
+ * has the string representation specified by @scontext.
+ * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient
+ * memory is available, or 0 on success.
+ */
+int security_context_to_sid(char *scontext, u32 scontext_len, u32 *sid)
+{
+       return security_context_to_sid_core(scontext, scontext_len,
+                                           sid, SECSID_NULL);
+}
+
+/**
+ * security_context_to_sid_default - Obtain a SID for a given security context,
+ * falling back to specified default if needed.
+ *
+ * @scontext: security context
+ * @scontext_len: length in bytes
+ * @sid: security identifier, SID
+ * @def_sid: default SID to assign on errror
+ *
+ * Obtains a SID associated with the security context that
+ * has the string representation specified by @scontext.
+ * The default SID is passed to the MLS layer to be used to allow
+ * kernel labeling of the MLS field if the MLS field is not present
+ * (for upgrading to MLS without full relabel).
+ * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient
+ * memory is available, or 0 on success.
+ */
+int security_context_to_sid_default(char *scontext, u32 scontext_len, u32 *sid, u32 def_sid)
+{
+       return security_context_to_sid_core(scontext, scontext_len,
+                                           sid, def_sid);
+}
+
 static int compute_sid_handle_invalid_context(
        struct context *scontext,
        struct context *tcontext,