Optional mandatory locking
Back in the early days, Unix lacked a mechanism for serializing access to shared files. Eventually, POSIX standardized an advisory locking mechanism invoked via the fcntl() system call; with advisory locks, a process can lock a region of a file for reading or writing, the latter granting exclusive access to that region. POSIX advisory locking mostly works, modulo certain shortcomings, and it was recently improved in Linux with the addition of file-private POSIX locks. But there is one obvious problem with advisory locks: they're advisory. All it takes is one process that isn't playing by the rules and the whole scheme falls down. As has been noted over the years, there is a lot of poorly written software out there; while advisory locks can work well within a single, well-written application (think of a database manager accessing its files, for example), they cannot be relied on in situations where arbitrary programs may try to access a file.
The answer from POSIX was mandatory locks, which can be thought of as advisory locks with more kludges added on top. If a file is made subject to mandatory locks (see below), then the locks that would have otherwise been advisory are enforced by the kernel. If a process write-locks a region of a file, any other process trying to read or write that region will be blocked until the lock is released. With mandatory locks, there is no longer a need to hope that every process accessing a file will observe the advisory locks.
Enforcing mandatory locks on every file access would be expensive, so the mandatory locks mechanism is restricted in scope. First of all, the filesystem must be mounted with the "-o mand" option to enable mandatory locks. Then any file subject to mandatory locking must be marked by setting the set-group-ID protection bit (but not the group execute bit). When those conditions are met, mandatory locks will be enforced on the file in question — to a point.
Linux has supported mandatory locks for a long time; the document describing them was written in 1996. It compares the kernel's implementation to the equivalent in other bleeding-edge operating systems like SunOS 4.1, Solaris 2, and HP-UX 9. Linux comes off relatively well in that comparison, but that is setting a low bar; everybody's implementation of mandatory locks was evidently bug-ridden, inconsistent, and unreliable. The kernel's document itself starts off with a section (added in 2007) titled "why you should avoid mandatory locking." Among other things, in Linux, the lock restrictions are enforced only at the beginning of an operation, so operations can race with locks that are established (by another process) halfway through.
In other words, Linux claims to support mandatory locks, but that support is incomplete and racy; developers who are serious about getting user-space locking right understand this and use something else.
While working on user namespaces, Eric Biederman recently ran into another issue: a process within a namespace can apply a mandatory lock to a file, then pass a descriptor for that file to a daemon outside of the namespace. That daemon will then freeze as soon as it tries to access the file descriptor. This is the sort of denial-of-service attack that namespaces are supposed to prevent, so this behavior is a bit of a problem. It can be fixed easily enough by limiting mandatory-lock enforcement to other processes in the same namespace, but Eric also has a more far-reaching solution in mind.
As has been noted, mandatory locks are inelegant, buggy, and subject to races on multiple operating systems. Furthermore, they have been that way for decades, and nobody has made the effort to fix them. Rather than try to fix the problems at this late date, Eric suggested:
The thinking here is that mandatory locking probably has almost no users at all. That might argue for its immediate removal, but that "almost" is the sticking point: breaking even a single ancient application goes against the kernel's "no regressions" rule. So the next best thing is to slowly make the feature harder to get at and to see if anything breaks.
The resulting discussion among filesystem developers was remarkably
one-sided; there is little love for the mandatory-locking feature in the
development community. There were some worries that Samba might rely on
mandatory locking, but Jeremy Allison put those
concerns to rest. So Jeff Layton quickly queued the patch and said that, in the absence
of objections, he would push it during the 4.5 merge window. No such
objections have been heard, so it appears that, in 4.5, the mandatory locks
feature will be optional and slated for eventual (if distant) removal.
Index entries for this article | |
---|---|
Kernel | Filesystems/POSIX locks |
Posted Dec 10, 2015 4:45 UTC (Thu)
by lambda (subscriber, #40735)
[Link]
Just to note, mandatory locking in Samba to SMB clients causes various problems as well; at the very least, OS X applications mostly don't expect mandatory locking, but get it when mounting an SMB volume, causing all kinds of fun like Photoshop not being able to save a file if it's selected in the Finder, since the finder is trying to preview it and thus Photoshop can't obtain a mandatory exclusive lock.
Mandatory locking seems like it would solve problems, but in practice, applications have files open for read for inessential operations like previewing, indexing, and virus scanning, and having those operations cause actual important writes to fail because they couldn't get a lock actually causes more problems than it solves.
Posted Dec 10, 2015 10:24 UTC (Thu)
by cuboci (subscriber, #9641)
[Link] (15 responses)
Someone uploads a file to a server. Upon completion some service does something with that file.
On the server side you have to have a way to know when the transfer is complete. In an ideal world the user would either upload the file with a temporary name and then rename it on the server or upload a second 'flag' file indicating completion. Unsurprisingly, (some) users are dumb and incapable of doing either in practice. So you have to fall back on some other mechanism.
I thought I could use locks that I would only be able to acquire once all other processes finished accessing the file. As it turns out, there's no such mechanism on Linux. Advisory locks are of no use here, mandatory locks are buggy and hard to use anyway. The only way is to wait for a certain amount of time (say, five minutes or so) and check if the file has changed in that time. But that can break down due to bad network connections, too.
So, I'm stuck with an impractical way of doing what I want that is also prone to errors just because Linux lacks proper file locking mechanisms. Sad.
Posted Dec 10, 2015 13:13 UTC (Thu)
by philipstorry (subscriber, #45926)
[Link] (8 responses)
Use a database?
A database should have all the correct locking you'll need. Granted, you shouldn't put the file being uploaded into the database - but you could use it for the operation status flag.
It's overkill. But after having looked at file locking mechanisms I began to understand why (some) developers use databases so often, and sometimes for what are apparently trivial things.
Posted Dec 10, 2015 13:27 UTC (Thu)
by cuboci (subscriber, #9641)
[Link] (7 responses)
Posted Dec 10, 2015 15:59 UTC (Thu)
by alankila (guest, #47141)
[Link] (4 responses)
Posted Dec 10, 2015 19:55 UTC (Thu)
by cuboci (subscriber, #9641)
[Link] (3 responses)
Posted Dec 10, 2015 20:19 UTC (Thu)
by iabervon (subscriber, #722)
[Link]
Posted Dec 10, 2015 22:42 UTC (Thu)
by rotty (guest, #14630)
[Link]
Posted Dec 12, 2015 11:24 UTC (Sat)
by alankila (guest, #47141)
[Link]
Posted Dec 13, 2015 2:55 UTC (Sun)
by giraffedata (guest, #1954)
[Link] (1 responses)
Posted Dec 14, 2015 11:55 UTC (Mon)
by cuboci (subscriber, #9641)
[Link]
Posted Dec 10, 2015 20:58 UTC (Thu)
by abatters (✭ supporter ✭, #6932)
[Link] (2 responses)
Posted Dec 15, 2015 16:19 UTC (Tue)
by k8to (guest, #15413)
[Link]
Posted Dec 15, 2015 16:53 UTC (Tue)
by k8to (guest, #15413)
[Link]
Posted Dec 21, 2015 12:02 UTC (Mon)
by oldtomas (guest, #72579)
[Link] (2 responses)
This way you can hook yourself into the action (and even do different processing depending on your customer's credentials).
This is the way gitolite and friends work. For an example on how to do it with rsync, see [1].
Or set up a gitolite, add a few users, go into ~gitolite/.ssh/authorized_keys and follow the breadcrumbs from there.
Missing piece: convince ssh's sftp module to be called from your wrapper script. But I'd expect it to be sufficiently unixy and well-behaved as to just accept some command line parameters and then take the bulk of communication over stdio.
[1] <http://www.sakana.fr/blog/2008/05/07/securing-automated-r...>
Posted Dec 21, 2015 23:12 UTC (Mon)
by nix (subscriber, #2304)
[Link] (1 responses)
It can be more appealing than authorized_keys commands in some situations (particularly when you want to be able to this for more than one user on the server without frotzing with all their authorized_keys files).
Posted Dec 22, 2015 12:55 UTC (Tue)
by oldtomas (guest, #72579)
[Link]
So my hunch was right, thanks for clarifying that (gotta love the Unix Way :-)
> It can be more appealing than authorized_keys commands in some situations ([...] without frotzing with all their authorized_keys files)
The authorized_keys part serves a different and highly complementary purpose: if you want different clients to do different things depending on their identity (authentification + authorization). The possibility of "hooking in" is just a side-effect.
If you just want to hook in, perhaps substituting the sftp module by an "enhanced" one (which appropriately triggers things on transfer success/failure) would be most adequate, yes.
Posted Dec 10, 2015 12:44 UTC (Thu)
by jnareb (subscriber, #46500)
[Link] (2 responses)
Posted Dec 10, 2015 13:49 UTC (Thu)
by philipstorry (subscriber, #45926)
[Link] (1 responses)
My understanding was that Windows file locking was more a decision taken for backwards compatibility more than anything else. They decided to enforce the old DOS-style file locking (that you had if you loaded SHARE.EXE) when they went multi-user, as it was the cleanest and clearest way to do so and have existing applications understand what was going on if a file was locked.
As Windows NT was multi-user, they then went further and baked that file locking in to the OS components.
Of course, in practice none of this matters, except when you're trying to explain to someone why Windows inevitably requires a restart after a software installation/update...
Posted Dec 15, 2015 16:56 UTC (Tue)
by k8to (guest, #15413)
[Link]
(Not a common case, but it comes up.)
Or more likely you're trying to port some Unix software that happens to do rename swizzling on open files.
But agreed the reboot-on-update is the most common.
Posted Dec 10, 2015 13:12 UTC (Thu)
by jlayton (subscriber, #31672)
[Link]
It has always seemed like a bit of a hack anyway (you need a mount option _and_ a special mode-bit combo which is not at all intuitive), and the use-cases for it are pretty thin on the ground.
Posted Dec 15, 2015 7:52 UTC (Tue)
by neilbrown (subscriber, #359)
[Link] (3 responses)
This always struck me as a rather lame argument. If you have one process that isn't playing by the rules, then when it gets the mandatory write lock it can completely corrupt the file.
If you trust the other process, then advisory locking is plenty. If you don't then you give it a different UID and don't give it write permission at all. If you want an in-between relationship — “Trust, but verify” — you use IPC to a management daemon.
Posted Dec 16, 2015 14:45 UTC (Wed)
by nix (subscriber, #2304)
[Link] (2 responses)
My dim memories of the days in the 90s when I tried to use mandatory locking are that it was similar to NFS in those days -- as in, any block was uninterruptible and unkillable. This essentially means that any bug (or attack from malevolent untrusted program, but this was the 90s, we weren't thinking in those terms so much) elevates a possible file corruption all the way up to oh-crap-I-have-to-reboot-and-even-that-might-not-work territory. Is there any wonder nobody went near mandatory locking after one look at that?
Posted Dec 16, 2015 23:28 UTC (Wed)
by neilbrown (subscriber, #359)
[Link] (1 responses)
Nope. There is an enormous difference between co-operating processes and adversarial processes. Advisory locking is for friends that work together on a common goal and don't want to tread on each other's toes. IPC is for strangers with a contractual arrangement. They really are different scenarios and pretending you can drift smoothly from one to the other is a mistake.
I can agree that it would be nice if IPC were as easy as writing to a file, but I don't agree that you should be able to achieve IPC with minor modifications to code which is written to just write to a file.
Posted Dec 20, 2015 1:08 UTC (Sun)
by nix (subscriber, #2304)
[Link]
Optional mandatory locking
Optional mandatory locking
Optional mandatory locking
Optional mandatory locking
Optional mandatory locking
Optional mandatory locking
Optional mandatory locking
You could also use inotify, for example by incron to generate an event based on a file being open for writing being closed. There might be gotchas, but in principle, it should work (I've used it for auto-converting files uploaded via SMB).
Optional mandatory locking
Optional mandatory locking
It's worth noting that even if there were some file locking function that could let you block until the file isn't open for write, relying on that is still a hack in your situation, since there's no reason the program that generates the file, over which you have no control, couldn't open and close the file multiple times in the process.
Optional mandatory locking
Optional mandatory locking
lsof
lsof
lsof
Optional mandatory locking
Optional mandatory locking
Optional mandatory locking
Optional mandatory locking
Optional mandatory locking
Both the other subsystems are dead these days, as Windows has focused more and more on just being Windows.
Optional mandatory locking
Optional mandatory locking
Optional mandatory locking
Optional mandatory locking
Optional mandatory locking
Optional mandatory locking