Compare commits

..

14 Commits

Author SHA1 Message Date
Lennart Poettering faf1bb8244
Merge pull request #14085 from poettering/ask-password-api
make sure asking for a pw works in a container too if keyctl() and friends are blocked
2019-11-20 00:54:28 +01:00
Lennart Poettering fbcb630045 pam_systemd: prolong method call timeout when allocating session
Starting a session might involve starting the user@.service instance,
hence let's make the bus call timeout substantially longer.

Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=83828
2019-11-19 21:05:03 +01:00
Zbigniew Jędrzejewski-Szmek cbfc32819a
Merge pull request #14078 from poettering/cryptsetup-fixlets
trivial cryptsetup fixlets (mostly: use more STR_IN_SET())
2019-11-19 20:46:53 +01:00
Zbigniew Jędrzejewski-Szmek 321c911fc2
Merge pull request #14079 from poettering/pam-systemd-fixlets
trivial pam_systemd fixlets
2019-11-19 20:45:15 +01:00
Yu Watanabe 08de195825 udev: do not propagate error in executing PROGRAM and IMPORT{program}
Also, this adds more logs.

Fixes #14027.
2019-11-19 20:20:46 +01:00
Lennart Poettering 09a6b4f34f ask-password: skip kernel keyring logic if we see EPERM
Let's improve compat with container managers that block the keyring
logic and return EPERM for them.
2019-11-19 19:12:09 +01:00
Lennart Poettering e6376b6a41 errno: add new ERRNO_IS_NOT_SUPPORTED() helper 2019-11-19 19:12:09 +01:00
Lennart Poettering 9120aa820b cryptsetup: use STR_IN_SET() where appropriate
Note that this slightly changes behaviour: "none" is only allowed as
option, if it's the only option specified, but not in combination with
other options. I think this makes more sense, since it's the choice when
no options shall be specified.
2019-11-19 15:34:09 +01:00
Lennart Poettering 9c5253ffec cryptsetup: minor coding style clean-ups 2019-11-19 15:34:09 +01:00
Lennart Poettering dca81e2851 pam_systemd: add one more assert 2019-11-19 15:26:45 +01:00
Lennart Poettering 8d46418e93 pam_systemd: don't use PAM_SYSTEM_ERR for something that isn't precisely a system error
It's not really clear which PAM errors to use for which conditions, but
something called PAM_SYSTEM_ERR should probably not be used when the
error is not the result of some system call failure.
2019-11-19 15:26:45 +01:00
Lennart Poettering 1798f5afe3 pam-systemd: voidify pam_get_item() calls 2019-11-19 15:26:45 +01:00
Lennart Poettering 42e6680976 pam-systemd: remove duplicate error logging 2019-11-19 15:26:45 +01:00
Lennart Poettering d9608d40bc pam-systemd: include PAM error code in all our log messages where that makes sense 2019-11-19 11:53:15 +01:00
6 changed files with 74 additions and 57 deletions

View File

@ -86,3 +86,11 @@ static inline bool ERRNO_IS_RESOURCE(int r) {
ENFILE,
ENOMEM);
}
/* Three different errors for "operation/system call/ioctl not supported" */
static inline bool ERRNO_IS_NOT_SUPPORTED(int r) {
return IN_SET(abs(r),
EOPNOTSUPP,
ENOTTY,
ENOSYS);
}

View File

@ -228,7 +228,7 @@ static int parse_one_option(const char *option) {
if (r < 0)
return log_error_errno(r, "Failed to parse %s: %m", option);
} else if (!streq(option, "none"))
} else
log_warning("Encountered unknown /etc/crypttab option '%s', ignoring.", option);
return 0;
@ -253,10 +253,10 @@ static int parse_options(const char *options) {
}
/* sanity-check options */
if (arg_type != NULL && !streq(arg_type, CRYPT_PLAIN)) {
if (arg_offset)
if (arg_type && !streq(arg_type, CRYPT_PLAIN)) {
if (arg_offset != 0)
log_warning("offset= ignored with type %s", arg_type);
if (arg_skip)
if (arg_skip != 0)
log_warning("skip= ignored with type %s", arg_type);
}
@ -462,11 +462,13 @@ static int attach_tcrypt(
return 0;
}
static int attach_luks_or_plain(struct crypt_device *cd,
const char *name,
const char *key_file,
char **passwords,
uint32_t flags) {
static int attach_luks_or_plain(
struct crypt_device *cd,
const char *name,
const char *key_file,
char **passwords,
uint32_t flags) {
int r = 0;
bool pass_volume_key = false;
@ -538,6 +540,7 @@ static int attach_luks_or_plain(struct crypt_device *cd,
}
if (r < 0)
return log_error_errno(r, "Failed to activate with key file '%s': %m", key_file);
} else {
char **p;
@ -632,25 +635,21 @@ static int run(int argc, char *argv[]) {
if (argc < 4)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "attach requires at least two arguments.");
if (argc >= 5 &&
argv[4][0] &&
!streq(argv[4], "-") &&
!streq(argv[4], "none")) {
if (!path_is_absolute(argv[4]))
log_warning("Password file path '%s' is not absolute. Ignoring.", argv[4]);
else
if (argc >= 5 && !STR_IN_SET(argv[4], "", "-", "none")) {
if (path_is_absolute(argv[4]))
key_file = argv[4];
else
log_warning("Password file path '%s' is not absolute. Ignoring.", argv[4]);
}
if (argc >= 6 && argv[5][0] && !streq(argv[5], "-")) {
if (argc >= 6 && !STR_IN_SET(argv[5], "", "-", "none")) {
r = parse_options(argv[5]);
if (r < 0)
return r;
}
/* A delicious drop of snake oil */
mlockall(MCL_FUTURE);
(void) mlockall(MCL_FUTURE);
if (arg_header) {
log_debug("LUKS header: %s", arg_header);
@ -723,11 +722,7 @@ static int run(int argc, char *argv[]) {
if (streq_ptr(arg_type, CRYPT_TCRYPT))
r = attach_tcrypt(cd, argv[2], key_file, passwords, flags);
else
r = attach_luks_or_plain(cd,
argv[2],
key_file,
passwords,
flags);
r = attach_luks_or_plain(cd, argv[2], key_file, passwords, flags);
if (r >= 0)
break;
if (r != -EAGAIN)

View File

@ -36,6 +36,8 @@
#include "strv.h"
#include "terminal-util.h"
#define LOGIN_SLOW_BUS_CALL_TIMEOUT_USEC (2*USEC_PER_MINUTE)
static int parse_argv(
pam_handle_t *handle,
int argc, const char **argv,
@ -50,28 +52,30 @@ static int parse_argv(
assert(argc == 0 || argv);
for (i = 0; i < (unsigned) argc; i++) {
if (startswith(argv[i], "class=")) {
const char *p;
if ((p = startswith(argv[i], "class="))) {
if (class)
*class = argv[i] + 6;
*class = p;
} else if (startswith(argv[i], "type=")) {
} else if ((p = startswith(argv[i], "type="))) {
if (type)
*type = argv[i] + 5;
*type = p;
} else if (startswith(argv[i], "desktop=")) {
} else if ((p = startswith(argv[i], "desktop="))) {
if (desktop)
*desktop = argv[i] + 8;
*desktop = p;
} else if (streq(argv[i], "debug")) {
if (debug)
*debug = true;
} else if (startswith(argv[i], "debug=")) {
} else if ((p = startswith(argv[i], "debug="))) {
int k;
k = parse_boolean(argv[i] + 6);
k = parse_boolean(p);
if (k < 0)
pam_syslog(handle, LOG_WARNING, "Failed to parse debug= argument, ignoring.");
pam_syslog(handle, LOG_WARNING, "Failed to parse debug= argument, ignoring: %s", p);
else if (debug)
*debug = k;
@ -97,7 +101,7 @@ static int get_user_data(
r = pam_get_user(handle, &username, NULL);
if (r != PAM_SUCCESS) {
pam_syslog(handle, LOG_ERR, "Failed to get user name.");
pam_syslog(handle, LOG_ERR, "Failed to get user name: %s", pam_strerror(handle, r));
return r;
}
@ -383,7 +387,7 @@ static int update_environment(pam_handle_t *handle, const char *key, const char
r = pam_misc_setenv(handle, key, value, 0);
if (r != PAM_SUCCESS)
pam_syslog(handle, LOG_ERR, "Failed to set environment variable %s.", key);
pam_syslog(handle, LOG_ERR, "Failed to set environment variable %s: %s", key, pam_strerror(handle, r));
return r;
}
@ -391,6 +395,7 @@ static int update_environment(pam_handle_t *handle, const char *key, const char
static bool validate_runtime_directory(pam_handle_t *handle, const char *path, uid_t uid) {
struct stat st;
assert(handle);
assert(path);
/* Just some extra paranoia: let's not set $XDG_RUNTIME_DIR if the directory we'd set it to isn't actually set
@ -459,10 +464,8 @@ _public_ PAM_EXTERN int pam_sm_open_session(
pam_syslog(handle, LOG_DEBUG, "pam-systemd initializing");
r = get_user_data(handle, &username, &pw);
if (r != PAM_SUCCESS) {
pam_syslog(handle, LOG_ERR, "Failed to get user data.");
if (r != PAM_SUCCESS)
return r;
}
/* Make sure we don't enter a loop by talking to
* systemd-logind when it is actually waiting for the
@ -470,7 +473,7 @@ _public_ PAM_EXTERN int pam_sm_open_session(
* "systemd-user" we simply set XDG_RUNTIME_DIR and
* leave. */
pam_get_item(handle, PAM_SERVICE, (const void**) &service);
(void) pam_get_item(handle, PAM_SERVICE, (const void**) &service);
if (streq_ptr(service, "systemd-user")) {
char rt[STRLEN("/run/user/") + DECIMAL_STR_MAX(uid_t)];
@ -478,7 +481,7 @@ _public_ PAM_EXTERN int pam_sm_open_session(
if (validate_runtime_directory(handle, rt, pw->pw_uid)) {
r = pam_misc_setenv(handle, "XDG_RUNTIME_DIR", rt, 0);
if (r != PAM_SUCCESS) {
pam_syslog(handle, LOG_ERR, "Failed to set runtime dir.");
pam_syslog(handle, LOG_ERR, "Failed to set runtime dir: %s", pam_strerror(handle, r));
return r;
}
}
@ -492,10 +495,10 @@ _public_ PAM_EXTERN int pam_sm_open_session(
/* Otherwise, we ask logind to create a session for us */
pam_get_item(handle, PAM_XDISPLAY, (const void**) &display);
pam_get_item(handle, PAM_TTY, (const void**) &tty);
pam_get_item(handle, PAM_RUSER, (const void**) &remote_user);
pam_get_item(handle, PAM_RHOST, (const void**) &remote_host);
(void) pam_get_item(handle, PAM_XDISPLAY, (const void**) &display);
(void) pam_get_item(handle, PAM_TTY, (const void**) &tty);
(void) pam_get_item(handle, PAM_RUSER, (const void**) &remote_user);
(void) pam_get_item(handle, PAM_RHOST, (const void**) &remote_host);
seat = getenv_harder(handle, "XDG_SEAT", NULL);
cvtnr = getenv_harder(handle, "XDG_VTNR", NULL);
@ -652,7 +655,7 @@ _public_ PAM_EXTERN int pam_sm_open_session(
return PAM_SYSTEM_ERR;
}
r = sd_bus_call(bus, m, 0, &error, &reply);
r = sd_bus_call(bus, m, LOGIN_SLOW_BUS_CALL_TIMEOUT_USEC, &error, &reply);
if (r < 0) {
if (sd_bus_error_has_name(&error, BUS_ERROR_SESSION_BUSY)) {
if (debug)
@ -660,7 +663,7 @@ _public_ PAM_EXTERN int pam_sm_open_session(
return PAM_SUCCESS;
} else {
pam_syslog(handle, LOG_ERR, "Failed to create session: %s", bus_error_message(&error, r));
return PAM_SYSTEM_ERR;
return PAM_SESSION_ERR;
}
}
@ -737,7 +740,7 @@ _public_ PAM_EXTERN int pam_sm_open_session(
r = pam_set_data(handle, "systemd.existing", INT_TO_PTR(!!existing), NULL);
if (r != PAM_SUCCESS) {
pam_syslog(handle, LOG_ERR, "Failed to install existing flag.");
pam_syslog(handle, LOG_ERR, "Failed to install existing flag: %s", pam_strerror(handle, r));
return r;
}
@ -750,7 +753,7 @@ _public_ PAM_EXTERN int pam_sm_open_session(
r = pam_set_data(handle, "systemd.session-fd", FD_TO_PTR(session_fd), NULL);
if (r != PAM_SUCCESS) {
pam_syslog(handle, LOG_ERR, "Failed to install session fd.");
pam_syslog(handle, LOG_ERR, "Failed to install session fd: %s", pam_strerror(handle, r));
safe_close(session_fd);
return r;
}

View File

@ -168,7 +168,12 @@ static int ask_password_keyring(const char *keyname, AskPasswordFlags flags, cha
return -EUNATCH;
r = lookup_key(keyname, &serial);
if (r == -ENOSYS) /* when retrieving the distinction doesn't matter */
if (ERRNO_IS_NOT_SUPPORTED(r) || r == -EPERM) /* when retrieving the distinction between "kernel or
* container manager don't support or allow this" and
* "no matching key known" doesn't matter. Note that we
* propagate EACCESS here (even if EPERM not) since
* that is used if the keyring is available but we lack
* access to the key. */
return -ENOKEY;
if (r < 0)
return r;

View File

@ -1014,7 +1014,9 @@ void udev_event_execute_run(UdevEvent *event, usec_t timeout_usec) {
log_device_debug(event->dev, "Running command \"%s\"", command);
r = udev_event_spawn(event, timeout_usec, false, command, NULL, 0);
if (r > 0) /* returned value is positive when program fails */
if (r < 0)
log_device_warning_errno(event->dev, r, "Failed to execute '%s', ignoring: %m", command);
else if (r > 0) /* returned value is positive when program fails */
log_device_debug(event->dev, "Command \"%s\" returned %d (error), ignoring.", command, r);
}
}

View File

@ -1665,10 +1665,13 @@ static int udev_rule_apply_token_to_event(
log_rule_debug(dev, rules, "Running PROGRAM '%s'", buf);
r = udev_event_spawn(event, timeout_usec, true, buf, result, sizeof(result));
if (r < 0)
return log_rule_error_errno(dev, rules, r, "Failed to execute '%s': %m", buf);
if (r > 0)
if (r != 0) {
if (r < 0)
log_rule_warning_errno(dev, rules, r, "Failed to execute '%s', ignoring: %m", buf);
else /* returned value is positive when program fails */
log_rule_debug(dev, rules, "Command \"%s\" returned %d (error), ignoring", buf, r);
return token->op == OP_NOMATCH;
}
delete_trailing_chars(result, "\n");
count = util_replace_chars(result, UDEV_ALLOWED_CHARS_INPUT);
@ -1732,10 +1735,11 @@ static int udev_rule_apply_token_to_event(
log_rule_debug(dev, rules, "Importing properties from results of '%s'", buf);
r = udev_event_spawn(event, timeout_usec, true, buf, result, sizeof result);
if (r < 0)
return log_rule_error_errno(dev, rules, r, "Failed to execute '%s': %m", buf);
if (r > 0) {
log_rule_debug(dev, rules, "Command \"%s\" returned %d (error), ignoring", buf, r);
if (r != 0) {
if (r < 0)
log_rule_warning_errno(dev, rules, r, "Failed to execute '%s', ignoring: %m", buf);
else /* returned value is positive when program fails */
log_rule_debug(dev, rules, "Command \"%s\" returned %d (error), ignoring", buf, r);
return token->op == OP_NOMATCH;
}