+ return 0;
+
+out_free:
+ /* don't leak context string if security_sid_to_context had an error */
+ if (*mount_options && i)
+ for (; i > 0; i--)
+ kfree((*mount_options)[i-1]);
+ kfree(*mount_options);
+ *mount_options = NULL;
+ kfree(*mnt_opts_flags);
+ *mnt_opts_flags = NULL;
+ *num_opts = 0;
+ return rc;
+}
+
+static int bad_option(struct superblock_security_struct *sbsec, char flag,
+ u32 old_sid, u32 new_sid)
+{
+ /* check if the old mount command had the same options */
+ if (sbsec->initialized)
+ if (!(sbsec->flags & flag) ||
+ (old_sid != new_sid))
+ return 1;
+
+ /* check if we were passed the same options twice,
+ * aka someone passed context=a,context=b
+ */
+ if (!sbsec->initialized)
+ if (sbsec->flags & flag)
+ return 1;
+ return 0;
+}
+/*
+ * Allow filesystems with binary mount data to explicitly set mount point
+ * labeling information.
+ */
+int selinux_set_mnt_opts(struct super_block *sb, char **mount_options,
+ int *flags, int num_opts)
+{
+ int rc = 0, i;
+ struct task_security_struct *tsec = current->security;
+ struct superblock_security_struct *sbsec = sb->s_security;
+ const char *name = sb->s_type->name;
+ struct inode *inode = sbsec->sb->s_root->d_inode;
+ struct inode_security_struct *root_isec = inode->i_security;
+ u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
+ u32 defcontext_sid = 0;