summaryrefslogtreecommitdiff
path: root/doc/internals/lockdown.mdwn
diff options
context:
space:
mode:
Diffstat (limited to 'doc/internals/lockdown.mdwn')
-rw-r--r--doc/internals/lockdown.mdwn44
1 files changed, 44 insertions, 0 deletions
diff --git a/doc/internals/lockdown.mdwn b/doc/internals/lockdown.mdwn
new file mode 100644
index 000000000..a7775cd3a
--- /dev/null
+++ b/doc/internals/lockdown.mdwn
@@ -0,0 +1,44 @@
+Object files stored in `.git/annex/objects` are each put in their own directory.
+This allows the write bit to be removed from both the file, and its directory,
+which prevents accidentially deleting or changing the file contents.
+
+The reasoning for doing this follows:
+
+Normally with git, once you have committed a file, editing the file in the
+working tree cannot cause you to lose the committed version. This is an
+important property of git. Of course you can `rm -rf .git` and delete
+commits if you like (before you've pushed them). But you can't lose a
+committed version of the file because of something you do with the working
+tree version.
+
+It's easy for git to do this, because committing a file makes a copy of it.
+But git-annex does not make a local copy of a file added to it, because
+the file could be very large.
+
+So, it's important for git-annex to find another way to preserve the expected
+property that once committed, you cannot accidentially lose a file.
+The most important protection it makes is just to remove the write bit of
+the file. Thus preventing programs from modifying it.
+
+But, that does not prevent any program that might follow the symlink and
+delete the symlinked file. This might seem an unlikely thing for a program to
+do at first, but consider a command like:
+`tar cf foo.tar foo --remove-files --dereference`
+
+When I tested this, I didn't know if it would remove the file foo symlinked
+to or not! It turned out that my tar doesn't remove it. But it could
+have easily went the other way.
+
+Rather than needing to worry about every possible program that might
+decide to do something like this, git-annex removes the write bit from the
+directory containing the annexed object, as well as removing the write
+bit from the file. (The only bad consequence of this is that `rm -rf .git`
+doesn't work unless you first run `chmod -R +w .git`)
+
+----
+
+It's known that this lockdown mechanism is incomplete. The worst hole in
+it is that if you explicitly run `chmod +w` on an annexed file in the working
+tree, this follows the symlink and allows writing to the file. It would be
+better to make the files fully immutable. But most systems either don't
+support immutable attributes, or only let root make files immutable.