#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
+#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include "parse-util.h"
#include "path-util.h"
#include "proc-cmdline.h"
+#include "process-util.h"
#include "selinux-util.h"
#include "smack-util.h"
#include "stat-util.h"
#include "string-table.h"
#include "string-util.h"
+#include "user-util.h"
#include "util.h"
#include "virt.h"
return r;
equal = !!strchr(c->parameter, '=');
- p = line;
- for (;;) {
+ for (p = line;;) {
_cleanup_free_ char *word = NULL;
bool found;
return false;
}
+static int condition_test_user(Condition *c) {
+ uid_t id;
+ int r;
+ _cleanup_free_ char *username = NULL;
+ const char *u;
+
+ assert(c);
+ assert(c->parameter);
+ assert(c->type == CONDITION_USER);
+
+ r = parse_uid(c->parameter, &id);
+ if (r >= 0)
+ return id == getuid() || id == geteuid();
+
+ if (streq("@system", c->parameter))
+ return getuid() <= SYSTEM_UID_MAX || geteuid() <= SYSTEM_UID_MAX;
+
+ username = getusername_malloc();
+ if (!username)
+ return -ENOMEM;
+
+ if (streq(username, c->parameter))
+ return 1;
+
+ if (getpid_cached() == 1)
+ return streq(c->parameter, "root");
+
+ u = c->parameter;
+ r = get_user_creds(&u, &id, NULL, NULL, NULL);
+ if (r < 0)
+ return 0;
+
+ return id == getuid() || id == geteuid();
+}
+
+static int condition_test_group(Condition *c) {
+ gid_t id;
+ int r;
+
+ assert(c);
+ assert(c->parameter);
+ assert(c->type == CONDITION_GROUP);
+
+ r = parse_gid(c->parameter, &id);
+ if (r >= 0)
+ return in_gid(id);
+
+ /* Avoid any NSS lookups if we are PID1 */
+ if (getpid_cached() == 1)
+ return streq(c->parameter, "root");
+
+ return in_group(c->parameter) > 0;
+}
+
static int condition_test_virtualization(Condition *c) {
int b, v;
assert(c->parameter);
assert(c->type == CONDITION_VIRTUALIZATION);
+ if (streq(c->parameter, "private-users"))
+ return running_in_userns();
+
v = detect_virtualization();
if (v < 0)
return v;
/* First, compare with yes/no */
b = parse_boolean(c->parameter);
-
- if (v > 0 && b > 0)
- return true;
-
- if (v == 0 && b == 0)
- return true;
+ if (b >= 0)
+ return b == !!v;
/* Then, compare categorization */
- if (VIRTUALIZATION_IS_VM(v) && streq(c->parameter, "vm"))
- return true;
+ if (streq(c->parameter, "vm"))
+ return VIRTUALIZATION_IS_VM(v);
- if (VIRTUALIZATION_IS_CONTAINER(v) && streq(c->parameter, "container"))
- return true;
+ if (streq(c->parameter, "container"))
+ return VIRTUALIZATION_IS_CONTAINER(v);
/* Finally compare id */
return v != VIRTUALIZATION_NONE && streq(c->parameter, virtualization_to_string(v));
assert(c->type == CONDITION_SECURITY);
if (streq(c->parameter, "selinux"))
- return mac_selinux_have();
+ return mac_selinux_use();
if (streq(c->parameter, "smack"))
return mac_smack_use();
if (streq(c->parameter, "apparmor"))
uint64_t timestamp;
int r;
- r = parse_env_file(p, NULL, "TimestampNSec", ×tamp_str, NULL);
+ r = parse_env_file(p, NULL, "TIMESTAMP_NSEC", ×tamp_str, NULL);
if (r < 0) {
- log_error_errno(-r, "Failed to parse timestamp file '%s', using mtime: %m", p);
+ log_error_errno(r, "Failed to parse timestamp file '%s', using mtime: %m", p);
return true;
} else if (r == 0) {
log_debug("No data in timestamp file '%s', using mtime", p);
r = safe_atou64(timestamp_str, ×tamp);
if (r < 0) {
- log_error_errno(-r, "Failed to parse timestamp value '%s' in file '%s', using mtime: %m",
- timestamp_str, p);
+ log_error_errno(r, "Failed to parse timestamp value '%s' in file '%s', using mtime: %m", timestamp_str, p);
return true;
}
- other.st_mtim.tv_nsec = timestamp % NSEC_PER_SEC;
+ timespec_store(&other.st_mtim, timestamp);
}
return usr.st_mtim.tv_nsec > other.st_mtim.tv_nsec;
assert(c->parameter);
assert(c->type == CONDITION_PATH_IS_MOUNT_POINT);
- return path_is_mount_point(c->parameter, AT_SYMLINK_FOLLOW) > 0;
+ return path_is_mount_point(c->parameter, NULL, AT_SYMLINK_FOLLOW) > 0;
}
static int condition_test_path_is_read_write(Condition *c) {
[CONDITION_ARCHITECTURE] = condition_test_architecture,
[CONDITION_NEEDS_UPDATE] = condition_test_needs_update,
[CONDITION_FIRST_BOOT] = condition_test_first_boot,
+ [CONDITION_USER] = condition_test_user,
+ [CONDITION_GROUP] = condition_test_group,
[CONDITION_NULL] = condition_test_null,
};
[CONDITION_DIRECTORY_NOT_EMPTY] = "ConditionDirectoryNotEmpty",
[CONDITION_FILE_NOT_EMPTY] = "ConditionFileNotEmpty",
[CONDITION_FILE_IS_EXECUTABLE] = "ConditionFileIsExecutable",
+ [CONDITION_USER] = "ConditionUser",
+ [CONDITION_GROUP] = "ConditionGroup",
[CONDITION_NULL] = "ConditionNull"
};
[CONDITION_DIRECTORY_NOT_EMPTY] = "AssertDirectoryNotEmpty",
[CONDITION_FILE_NOT_EMPTY] = "AssertFileNotEmpty",
[CONDITION_FILE_IS_EXECUTABLE] = "AssertFileIsExecutable",
+ [CONDITION_USER] = "AssertUser",
+ [CONDITION_GROUP] = "AssertGroup",
[CONDITION_NULL] = "AssertNull"
};