From: Nir Soffer <nsoffer(a)redhat.com>
On Fedora 28, sanlock fails to create the lockfile before dropping
privileges, because /run/sanlock is owned by sanlock, and selinux
disables DAC_OVERRIDE.
To allow root to create the lockfile before dropping privileges
/run/sanlock is owned by group root, and group writable. Since sanlock
never write to the lockfile after dropping privileges, keep the lockfile
owned by root.
Here are /run/sanlock permissions with this change:
$ ls -lhdZ /run/sanlock
drwxrwxr-x. 2 sanlock root system_u:object_r:sanlock_var_run_t:s0 80 Nov 29 23:07
/run/sanlock
$ ls -lhZ /run/sanlock
total 4.0K
-rw-r--r--. 1 root root system_u:object_r:sanlock_var_run_t:s0 5 Nov 29 23:07
sanlock.pid
srw-rw----. 1 sanlock sanlock system_u:object_r:sanlock_var_run_t:s0 0 Nov 29 23:07
sanlock.sock
Signed-off-by: Nir Soffer <nsoffer(a)redhat.com>
---
src/lockfile.c | 12 ++++--------
src/main.c | 6 +++++-
2 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/src/lockfile.c b/src/lockfile.c
index 5a2518e..cffaaff 100644
--- a/src/lockfile.c
+++ b/src/lockfile.c
@@ -19,41 +19,44 @@
#include <time.h>
#include <syslog.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>
#include "sanlock_internal.h"
#include "log.h"
#include "lockfile.h"
int lockfile(const char *dir, const char *name, int uid, int gid)
{
char path[PATH_MAX];
char buf[16];
struct flock lock;
mode_t old_umask;
int fd, rv;
- old_umask = umask(0022);
+ /* Make rundir group writable, allowing creation of the lockfile when
+ * starting as root. */
+
+ old_umask = umask(0002);
rv = mkdir(dir, 0775);
if (rv < 0 && errno != EEXIST) {
umask(old_umask);
return rv;
}
umask(old_umask);
rv = chown(dir, uid, gid);
if (rv < 0) {
log_error("lockfile chown error %s: %s",
dir, strerror(errno));
return rv;
}
snprintf(path, PATH_MAX, "%s/%s", dir, name);
fd = open(path, O_CREAT|O_WRONLY|O_CLOEXEC, 0644);
if (fd < 0) {
log_error("lockfile open error %s: %s",
path, strerror(errno));
@@ -72,32 +75,25 @@ int lockfile(const char *dir, const char *name, int uid, int gid)
goto fail;
}
rv = ftruncate(fd, 0);
if (rv < 0) {
log_error("lockfile truncate error %s: %s",
path, strerror(errno));
goto fail;
}
memset(buf, 0, sizeof(buf));
snprintf(buf, sizeof(buf), "%d\n", getpid());
rv = write(fd, buf, strlen(buf));
if (rv <= 0) {
log_error("lockfile write error %s: %s",
path, strerror(errno));
goto fail;
}
- rv = fchown(fd, uid, gid);
- if (rv < 0) {
- log_error("lockfile fchown error %s: %s",
- path, strerror(errno));
- goto fail;
- }
-
return fd;
fail:
close(fd);
return -1;
}
diff --git a/src/main.c b/src/main.c
index b3898e2..9538cc5 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1665,42 +1665,46 @@ static int do_daemon(void)
setup_task_aio(&main_task, com.aio_arg, 0);
rv = client_alloc();
if (rv < 0)
return rv;
helper_ci = client_add(helper_status_fd, process_helper, helper_dead);
if (helper_ci < 0)
return rv;
strcpy(client[helper_ci].owner_name, "helper");
setup_signals();
setup_logging();
if (strcmp(run_dir, DEFAULT_RUN_DIR))
log_warn("Using non-standard run directory '%s'", run_dir);
if (!privileged)
log_warn("Running in unprivileged mode");
+ /* If we run as root, make run_dir owned by root, so we can create the
+ * lockfile when selinux disables DAC_OVERRIDE.
+ * See
https://danwalsh.livejournal.com/79643.html */
- fd = lockfile(run_dir, SANLK_LOCKFILE_NAME, com.uid, com.gid);
+ fd = lockfile(run_dir, SANLK_LOCKFILE_NAME, com.uid,
+ privileged ? 0 : com.gid);
if (fd < 0) {
close_logging();
return fd;
}
setup_host_name();
setup_uid_gid();
log_warn("sanlock daemon started %s host %s", VERSION, our_host_name_global);
setup_priority();
rv = thread_pool_create(DEFAULT_MIN_WORKER_THREADS, com.max_worker_threads);
if (rv < 0)
goto out;
rv = setup_listener();
if (rv < 0)
goto out_threads;
--
2.17.2