Make all files under a directory read-only without changing permissions?

First, some background:

  • /dev/md1 is a RAID-0 array serving as primary file store. It is mounted to /var/smb.
  • /dev/md2 is another RAID-0 array storing backup snapshots taken from /dev/md1. It is mounted to /var/smb/snapshots.
  • Three directories are made available via Samba: /var/smb/files (publicly-shared files), /var/smb/private (private files), and /var/smb/snapshots (providing read-only access to backup snapshots).

Only users in the smbusers group are allowed to access the files and snapshots shares; similarly, only users in the smbprivate group are allowed to access the files in private. Additionally, Linux permissions prohibit users not in the respective groups from accessing the files and private directories, both on the local system and within the snapshots Samba share.

This is great, because it means that we have a fully functional file server with a self-help “restore from backup” option (users can simply access the snapshots share and retrieve the file(s) they want to restore themselves), but so far I lack one key ingredient: Non-root access on the local system to the /var/smb/snapshots directory.

The snapshots must be strictly read-only to all regular users, however of course the file system must be mounted read-write to allow the backup operation to take place. The permissions on these directories are currently:

<a href="" class="__cf_email__" data-cfemail="a9dbc6c6dde9c6cdc0c7">[email protected]</a>:/var/smb# ll
total 40
drwxrwxr-x  7 root   root        4096 2011-04-11 15:18 ./
drwxr-xr-x 14 root   root        4096 2011-04-10 19:07 ../
drwxrwx--- 15 kromey smbusers    4096 2010-12-07 13:09 files/
drwxrwx---  7 kromey smbprivate  4096 2010-04-07 07:08 private/
drwxrwx---  3 root   root        4096 2011-04-11 15:16 snapshots/

Now, what I want is to provide access to the snapshots directory to non-root users, but in a strictly read-only fashion. I can’t mount /dev/md2 read-only, though, because I have to have it read-write to run backups; I can’t simply re-mount it read-write for a backup and then re-mount it back to read-only, because that provides a window of time when the backups could be written to by another user.

Previously I did this by making my snapshots directory a read-only NFS export (only to localhost) and mounting that locally (the original secured under a directory lacking traversal rights for non-root users), but this feels like a hack and there seems like there should be a better way to accomplish this. I did try the mount --bind option, but it seems to lack the ability to have different access levels (i.e. read-only versus read-write) on the two directories (unless I’m missing something: mount -r --bind dir1 dir2).

Any ideas how I can accomplish this without NFS, or is that my best option?

TL;DR: How can I make the contents of a file system available read-write to a select user, but strictly read-only to everyone else, while maintaining original permissions and ownerships on the files backed up to this file system?


Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

@Gilles was really close, just ever-so-slightly off the mark for Ubuntu 10.10 (I don’t have any reason to doubt he’s right for Debian Squeeze, and possibly others). By mounting my read-write snapshots directory under a folder that other users cannot access (e.g. /var/smb/hidden/snapshots, where /var/smb/hidden has permissions 770 and is owned by root:root), I can protect the read-write mount from other users. I can then use mount --bind followed by mount -o remount,ro to bind the mount to an accessible location, then make it read-only.

(The inverse (mount the original file system read-only, then bind it read-write) does not work; similarly, mounting the original read-only, then binding it read-only, then re-mounting the original read-write makes the bound directory also read-write.)

So to recap, here’s the solution:

mkdir /var/smb/hidden
chown root:root /var/smb/hidden
chmod 770 /var/smb/hidden
mkdir /var/smb/hidden/snapshots
mksdir /var/smb/snapshots
mount /dev/md2 /var/smb/hidden/snapshots
mount --bind /var/smb/hidden/snapshots /var/smb/snapshots
mount -o remount,ro /var/smb/snapshots

So there is a brief window of time where the backups are read-write and generally accessible, but it’s small enough to be usable for my needs. Some trickery with the permissions on /var/smb could protect it during this brief window (i.e. make it non-traversable, then bind the mount, then make it traversable again), if those brief milliseconds are too big a window.

Now I just have to put this all together in a script. Slip it into the start-up process right after everything is mounted perhaps, which should avoid any conflict that might be caused by Samba trying to share the directory I’m binding to.

Note: If your distro supports the mount -o bind,ro version as Gilles posted, I recommend that solution for you; my solution is here should only be used by folks on Ubuntu or other distros that won’t permit you to change mount options when binding to another directory.

Method 2

This answer works on Debian (tested on lenny and squeeze). After investigation, it seems to work only thanks to a Debian patch; users of other distributions such as Ubuntu may be out of luck.

You can use mount --bind. Mount the “real” filesystem under a directory that’s not publicly accessible. Make a read-only bind mount that’s more widely accessible. Make a read-write bind mount for the part you want to expose with read-write access.

mkdir /media/hidden /media/hidden/sdz99
chmod 700 /media/hidden
mount /dev/sdz99 /media/hidden/sdz99
mount -o bind,ro /media/hidden/sdz99/world-readable /media/world-readable
mount -o bind /media/hidden/sdz99/world-writable /media/world-writable

In your use case, I think you can do:
mkdir /var/smb/hidden
mv /var/smb/snapshot /var/smb/hidden
mkdir /var/smb/snapshot
chmod 700 /var/smb/hidden
chmod 755 /var/smb/hidden/snapshot
mount -o bind,ro /var/smb/hidden/snapshot /var/smb/hidden/snapshot

I.e. put the real snapshot directory under a restricted directory, but give snapshot read permissions for everyone. It won’t be directly accessible because its parent has restricted access. Bind-mount it read-only in an accessible location, so that everyone can read it through that path.

(Read-only bind mounts only became possible several years after bind mounts were introduced, so you might remember a time when they didn’t work. I don’t know offhand since when they work, but they already worked in Debian lenny (i.e. now oldstable).)

All methods was sourced from or, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Notify of
Inline Feedbacks
View all comments