11

We have an environment of a few thousand users running applications on about 40 clusters ranging in size from 20 compute nodes to 98,000 compute nodes. Users on these systems generate massive files (sometimes > 1PB) controlled by traditional unix permissions (ACLs usually aren't available or practical due to the specialized nature of the filesystem).

We currently have a program called "give", which is a suid-root program that allows a user to "give" a file to another user when group permissions are insufficient. So, a user would type something like the following to give a file to another user:

> give username-to-give-to filename-to-give ...

The receiving user can then use a command called "take" (part of the give program) to receive the file:

> take filename-to-receive

The permissions of the file are then effectively transferred over to the receiving user.

This program has been around for years and we'd like to revisit things from a security and functional point of view.

Our current plan of action is to remove the bit rot in our current implementation of "give" and package it up as an open source app before we redeploy it into production.

Does anyone have another method they use to transfer extremely large files between users when only traditional unix permissions are available?

Jon Bringhurst
  • 251
  • 2
  • 8
  • 1
    Is there some reason why you can't just create a shared directory where all users have access? – Zoredache Jun 18 '12 at 20:43
  • 1
    If there's a directory with shared access, then users without permission would have access to files as they're being shared. In this environment, sometimes file-names are sensitive as well. So, unfortunately, a shared directory isn't an option. With a shared directory, there's also a possibility of a third user tampering with the file. – Jon Bringhurst Jun 18 '12 at 22:12
  • Wouldn't be sufficient a cron job would would copy files itself? Example: user foo want to give file bar to user puppy. so he creates specialized directory which is scanned by cron job with a 'control' file containing receiving username. The cron jobs would read this 'control' file, if user is OK, destination directory has space is OK, the copy. You can still create a wrapper for 'give' to just create 'control' file to have historical compatibility. No need for suid-root, you can copy that file under non-root user and then sudo for changing ownership. – jirib Jun 19 '12 at 15:25
  • If you just want to change permissions, `chown` should do it.. It seems you want to also copy the file, once both parties involved have agreed. – zebediah49 Jun 19 '12 at 18:14
  • @JiriXichtkniha I do like the idea of a control file and a cron job. However, the files are too large to be copied. – Jon Bringhurst Jun 20 '12 at 14:59
  • OK, so move them ;) Anyway I would recommend some queueing mechanism. If you would have multiple copies in one shot, it could cause troubles. With some clever queueing you can make it very flexible, moving files after confirmation via mail etc... – jirib Jun 20 '12 at 21:07

5 Answers5

1

As xryl669 says you can use a directory to actually share the files. It should look like this:

$ ls -ld shared
drwxrws--- 2 root usergroup 4096 somedate shared
$ ls -l shared
drwx-wx--- 2 user1 usergroup 4096 somedate user1
drwx-wx--- 2 user2 usergroup 4096 somedate user2
drwx-wx--- 2 user3 usergroup 4096 somedate user3
drwx-wx--- 2 user4 usergroup 4096 somedate user4

The give command becomes

#!/bin/sh
#Use a random suffix to prevent guessing
RANDOM=$(dd if=/dev/urandom count=4 2> /dev/null | sha512sum | cut -d' ' -f1)
NEWNAME=/path/to/shared/$2/$1$RANDOM
#Move the file
mv $1 $NEWNAME
#Make it readable
chmod 440 $NEWNAME

The take command looks something like this:

$ cd /path/to/shared/user
$ ls
...
$ mv somefile ~
miniBill
  • 228
  • 2
  • 12
1

If the emitter is really willing to give the file away, you can use an SUID binary that moves the file to a directory that's writeable by all and has the sticky bit (like /tmp), then changes ownership to the new owner. chown(3) already takes care of removing the set-user-ID and set-group-ID bits for you. This way the new owner can do what he wants with the file, including moving it.

This directory writeable by all can belong to the user's home directory, in case you want to use multiple filesystems for home directories and want to make sure you don't cross filesystem boundaries as performance would immediately be terrible. In this case you'll probably want to make sure the recipient knows when a new file is offered.

E-mails would do the trick. A more Unixy solution would be a /etc/profile that lists your newly delivered files. Added bonus if you offer this feature with pam_echo (eg with file=/tmp/deliveries/%u, see pam_echo(8)). As with anything PAM-related, you'd want to check that all your implementations offer such a module first.

Pierre Carrier
  • 2,607
  • 17
  • 28
0

You could use a system with a shared directory, (possibly without execute perms.), where things for a given user are archived with a specific file name structure (to-$username_from-$username.tar, for example). Give makes the file and chowns it to the target user; take extracts the file and removes it.

If you want to do it as an actually move (IE, change file location and permissions; no copying because of the giant file size), you might be able to get away with moving to a shared directory with -x perms (so nobody can list files there), and the same chown method. mv, chown / mv.

zebediah49
  • 176
  • 7
0

I'd suggest to rewrite the app to indeed mimic a "give" and "take", but rather "push" and "pull" it from a protected directory. Your directory can be only accessible for the push/pull app - which handles the file moves. Alternatively, your app/script can create a random, temporary directory with permissions being set for the sender and receiver only.

Wish to have more security? You can PGP encrypt/sign the file (using the public key of the receiver).

In terms of redoing it from a "security and functional point of view", I'd strongly suggest not to create SUID programs. If you don't drop privileges in a proper way, you can virtually access any file on the system. If your program is buggy (buffer overflow, etc...) - one can exploit this to gain root access on your system.

ndrix
  • 199
  • 3
0

This is probably no use to you but for reference cp --reflink source target does thin copies of files using copy-on-write.

This means you could copy the file outright and only changed blocks would actually be copied. Unlike a hard link the new file has its own inode and metadata meaning you can then provide the copy of the file to the new user using standard chown stuff.

As far as I am aware this is a feature that is only available on OCFS2 and btrfs currently. I guess that does solve your problem but seeing as the availability of it is not widespread it probably wont be useful.

Matthew Ife
  • 22,927
  • 2
  • 54
  • 71