Print this page
*** NO COMMENTS ***

@@ -476,11 +476,16 @@
         if (mark_opened(lsp, otyp) == -1) {
                 mutex_exit(&lofi_lock);
                 return (EINVAL);
         }
 
+        if (lsp->ls_readonly && (flag & FWRITE)) {
         mutex_exit(&lofi_lock);
+                return (EROFS);
+        }
+
+        mutex_exit(&lofi_lock);
         return (0);
 }
 
 /*ARGSUSED*/
 static int

@@ -1618,15 +1623,17 @@
 /*
  * Find the lofi state for the given filename. We compare by vnode to
  * allow the global zone visibility into NGZ lofi nodes.
  */
 static int
-file_to_lofi_nocheck(char *filename, struct lofi_state **lspp)
+file_to_lofi_nocheck(char *filename, boolean_t readonly,
+    struct lofi_state **lspp)
 {
         struct lofi_state *lsp;
         vnode_t *vp = NULL;
         int err = 0;
+        int rdfiles = 0;
 
         ASSERT(MUTEX_HELD(&lofi_lock));
 
         if ((err = lookupname(filename, UIO_SYSSPACE, FOLLOW,
             NULLVPP, &vp)) != 0)

@@ -1644,16 +1651,34 @@
         for (lsp = list_head(&lofi_list); lsp != NULL;
             lsp = list_next(&lofi_list, lsp)) {
                 if (lsp->ls_vp == vp) {
                         if (lspp != NULL)
                                 *lspp = lsp;
+                        if (lsp->ls_readonly) {
+                                rdfiles++;
+                                /* Skip if '-r' is specified */
+                                if (readonly)
+                                        continue;
+                        }
                         goto out;
                 }
         }
 
         err = ENOENT;
 
+        /*
+         * If a filename is given as an argument for lofi_unmap, we shouldn't
+         * allow unmap if there are multiple read-only lofi devices associated
+         * with this file.
+         */
+        if (lspp != NULL) {
+                if (rdfiles == 1)
+                        err = 0;
+                else if (rdfiles > 1)
+                        err = EBUSY;
+        }
+
 out:
         if (vp != NULL)
                 VN_RELE(vp);
         return (err);
 }

@@ -1661,17 +1686,17 @@
 /*
  * Find the minor for the given filename, checking the zone can access
  * it.
  */
 static int
-file_to_lofi(char *filename, struct lofi_state **lspp)
+file_to_lofi(char *filename, boolean_t readonly, struct lofi_state **lspp)
 {
         int err = 0;
 
         ASSERT(MUTEX_HELD(&lofi_lock));
 
-        if ((err = file_to_lofi_nocheck(filename, lspp)) != 0)
+        if ((err = file_to_lofi_nocheck(filename, readonly, lspp)) != 0)
                 return (err);
 
         if ((err = lofi_access(*lspp)) != 0)
                 return (err);
 

@@ -2120,11 +2145,12 @@
                 free_lofi_ioctl(klip);
                 return (error);
         }
         mutex_exit(&curproc->p_lock);
 
-        if (file_to_lofi_nocheck(klip->li_filename, NULL) == 0) {
+        if (file_to_lofi_nocheck(klip->li_filename, klip->li_readonly,
+            NULL) == 0) {
                 error = EBUSY;
                 goto err;
         }
 
         if (pickminor) {

@@ -2241,10 +2267,12 @@
         }
 
         lsp->ls_kstat->ks_lock = &lsp->ls_kstat_lock;
         kstat_zone_add(lsp->ls_kstat, GLOBAL_ZONEID);
 
+        lsp->ls_readonly = klip->li_readonly;
+
         if ((error = lofi_init_crypto(lsp, klip)) != 0)
                 goto err;
 
         if ((error = lofi_init_compress(lsp)) != 0)
                 goto err;

@@ -2341,11 +2369,12 @@
         if (err != 0)
                 return (err);
 
         mutex_enter(&lofi_lock);
         if (byfilename) {
-                if ((err = file_to_lofi(klip->li_filename, &lsp)) != 0) {
+                if ((err = file_to_lofi(klip->li_filename, klip->li_readonly,
+                    &lsp)) != 0) {
                         mutex_exit(&lofi_lock);
                         return (err);
                 }
         } else if (klip->li_minor == 0) {
                 mutex_exit(&lofi_lock);

@@ -2458,20 +2487,23 @@
                     sizeof (klip->li_filename), CRED()) != 0) {
                         (void) strlcpy(klip->li_filename, "?",
                             sizeof (klip->li_filename));
                 }
 
+                klip->li_readonly = lsp->ls_readonly;
+
                 (void) strlcpy(klip->li_algorithm, lsp->ls_comp_algorithm,
                     sizeof (klip->li_algorithm));
                 klip->li_crypto_enabled = lsp->ls_crypto_enabled;
                 mutex_exit(&lofi_lock);
                 error = copy_out_lofi_ioctl(klip, ulip, ioctl_flag);
                 free_lofi_ioctl(klip);
                 return (error);
         case LOFI_GET_MINOR:
                 mutex_enter(&lofi_lock);
-                error = file_to_lofi(klip->li_filename, &lsp);
+                error = file_to_lofi(klip->li_filename,
+                    klip->li_readonly, &lsp);
                 if (error == 0)
                         klip->li_minor = getminor(lsp->ls_dev);
                 mutex_exit(&lofi_lock);
 
                 if (error == 0)

@@ -2479,11 +2511,12 @@
 
                 free_lofi_ioctl(klip);
                 return (error);
         case LOFI_CHECK_COMPRESSED:
                 mutex_enter(&lofi_lock);
-                error = file_to_lofi(klip->li_filename, &lsp);
+                error = file_to_lofi(klip->li_filename,
+                    klip->li_readonly, &lsp);
                 if (error != 0) {
                         mutex_exit(&lofi_lock);
                         free_lofi_ioctl(klip);
                         return (error);
                 }