To ensure consistency on power outage, files can be updated as follows (pseudocode):
echo original_contents > file
echo new_contents > /tmp_dir_in_same_fs/file.tmp
mv /tmp_dir_in_same_fs/file.tmp file
Now the thing is, if the files are in a folder root-owned, that rename operation gets a permission denied:
mkdir the_dir
echo original_contents > the_dir/file
echo new_contents > file.tmp
sudo chown root:root the_dir
sudo chmod 755 the_dir
mv file.tmp the_dir/file # permission denied
while:
echo new_contents > the_dir/file
works (but it's not as safe when it comes to consistency on power loss).
So I'm thinking about writing a small SUID program rename_suid
that will just check that the source & target files have the proper ownership, so the replacement can be performed.
Here's a proposed implementation:
/*! \file rename_suid.c
\brief rename file with SUID, provided target file is owned
by calling user and source file mode mode matches the target file's.
\license https://creativecommons.org/licenses/by-sa/3.0/
© cJ-so-rs@zougloub.eu 2018
*/
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int main(int argc, char ** argv)
{
int res;
if (argc != 3) {
fprintf(stderr, "Usage: %s <source> <target>\n", argv[0]);
return EINVAL;
}
char const * src = argv[1];
char const * dst = argv[2];
struct stat stat_src;
struct stat stat_dst;
int uid = getuid();
int euid = geteuid();
if (euid != 0) {
fprintf(stderr, "I am not root EUID, trouble ahead\n");
}
res = stat(src, &stat_src);
if (res != 0) {
perror("Cannot stat source file");
return errno;
}
res = stat(dst, &stat_dst);
if (res != 0) {
perror("Cannot stat target file");
return errno;
}
if (stat_src.st_uid != uid) {
perror("Bad source uid");
return EPERM
}
if (stat_dst.st_uid != uid) {
perror("Bad target uid");
return EPERM;
}
if (stat_src.st_mode != stat_dst.st_mode) {
fprintf(stderr, "Inconsistent source-target modes\n");
return EPERM;
}
res = rename(src, dst);
if (res != 0) {
perror("Cannot rename");
}
return errno;
}
The question is... am I missing something:
- Is there another solution to the problem?
- If not, does a similar tool exist?
- If such this tool is the only solution, could it, by its principle of operation, cause unforeseen security issues?
- Any (security) problem with the proposed implementation?
Thanks,