|
|
0331fa |
diff --color -ru a/libcap/cap_proc.c b/libcap/cap_proc.c
|
|
|
0331fa |
--- a/libcap/cap_proc.c 2021-12-22 12:33:20.739126763 +0100
|
|
|
0331fa |
+++ b/libcap/cap_proc.c 2021-12-22 12:33:53.195733115 +0100
|
|
|
0331fa |
@@ -406,6 +406,29 @@
|
|
|
0331fa |
}
|
|
|
0331fa |
|
|
|
0331fa |
/*
|
|
|
0331fa |
+ * cap_prctl performs a prctl() 6 argument call on the current
|
|
|
0331fa |
+ * thread. Use cap_prctlw() if you want to perform a POSIX semantics
|
|
|
0331fa |
+ * prctl() system call.
|
|
|
0331fa |
+ */
|
|
|
0331fa |
+int cap_prctl(long int pr_cmd, long int arg1, long int arg2,
|
|
|
0331fa |
+ long int arg3, long int arg4, long int arg5)
|
|
|
0331fa |
+{
|
|
|
0331fa |
+ return prctl(pr_cmd, arg1, arg2, arg3, arg4, arg5);
|
|
|
0331fa |
+}
|
|
|
0331fa |
+
|
|
|
0331fa |
+/*
|
|
|
0331fa |
+ * cap_prctlw performs a POSIX semantics prctl() call. That is a 6 arg
|
|
|
0331fa |
+ * prctl() call that executes on all available threads when libpsx is
|
|
|
0331fa |
+ * linked. The suffix 'w' refers to the fact one only ever needs to
|
|
|
0331fa |
+ * invoke this is if the call will write some kernel state.
|
|
|
0331fa |
+ */
|
|
|
0331fa |
+int cap_prctlw(long int pr_cmd, long int arg1, long int arg2,
|
|
|
0331fa |
+ long int arg3, long int arg4, long int arg5)
|
|
|
0331fa |
+{
|
|
|
0331fa |
+ return _libcap_wprctl6(&multithread, pr_cmd, arg1, arg2, arg3, arg4, arg5);
|
|
|
0331fa |
+}
|
|
|
0331fa |
+
|
|
|
0331fa |
+/*
|
|
|
0331fa |
* Some predefined constants
|
|
|
0331fa |
*/
|
|
|
0331fa |
#define CAP_SECURED_BITS_BASIC \
|
|
|
0331fa |
diff --color -ru a/libcap/include/sys/capability.h b/libcap/include/sys/capability.h
|
|
|
0331fa |
--- a/libcap/include/sys/capability.h 2021-02-05 06:52:17.000000000 +0100
|
|
|
0331fa |
+++ b/libcap/include/sys/capability.h 2021-12-22 12:33:53.196733134 +0100
|
|
|
0331fa |
@@ -175,6 +175,11 @@
|
|
|
0331fa |
extern unsigned cap_get_secbits(void);
|
|
|
0331fa |
extern int cap_set_secbits(unsigned bits);
|
|
|
0331fa |
|
|
|
0331fa |
+extern int cap_prctl(long int pr_cmd, long int arg1, long int arg2,
|
|
|
0331fa |
+ long int arg3, long int arg4, long int arg5);
|
|
|
0331fa |
+extern int cap_prctlw(long int pr_cmd, long int arg1, long int arg2,
|
|
|
0331fa |
+ long int arg3, long int arg4, long int arg5);
|
|
|
0331fa |
+
|
|
|
0331fa |
extern int cap_setuid(uid_t uid);
|
|
|
0331fa |
extern int cap_setgroups(gid_t gid, size_t ngroups, const gid_t groups[]);
|
|
|
0331fa |
|
|
|
0331fa |
diff --color -ru a/pam_cap/pam_cap.c b/pam_cap/pam_cap.c
|
|
|
0331fa |
--- a/pam_cap/pam_cap.c 2021-12-22 12:33:20.740126781 +0100
|
|
|
0331fa |
+++ b/pam_cap/pam_cap.c 2021-12-22 12:33:53.196733134 +0100
|
|
|
0331fa |
@@ -21,6 +21,7 @@
|
|
|
0331fa |
#include <string.h>
|
|
|
0331fa |
#include <syslog.h>
|
|
|
0331fa |
#include <sys/capability.h>
|
|
|
0331fa |
+#include <sys/prctl.h>
|
|
|
0331fa |
#include <sys/types.h>
|
|
|
0331fa |
#include <linux/limits.h>
|
|
|
0331fa |
|
|
|
0331fa |
@@ -33,8 +34,11 @@
|
|
|
0331fa |
|
|
|
0331fa |
struct pam_cap_s {
|
|
|
0331fa |
int debug;
|
|
|
0331fa |
+ int keepcaps;
|
|
|
0331fa |
+ int defer;
|
|
|
0331fa |
const char *user;
|
|
|
0331fa |
const char *conf_filename;
|
|
|
0331fa |
+ pam_handle_t *pamh;
|
|
|
0331fa |
};
|
|
|
0331fa |
|
|
|
0331fa |
/*
|
|
|
0331fa |
@@ -178,6 +182,33 @@
|
|
|
0331fa |
}
|
|
|
0331fa |
|
|
|
0331fa |
/*
|
|
|
0331fa |
+ * This is the "defer" cleanup function that actually applies the IAB
|
|
|
0331fa |
+ * tuple. This happens really late in the PAM session, hopefully after
|
|
|
0331fa |
+ * the application has performed its setuid() function.
|
|
|
0331fa |
+ */
|
|
|
0331fa |
+static void iab_apply(pam_handle_t *pamh, void *data, int error_status)
|
|
|
0331fa |
+{
|
|
|
0331fa |
+ cap_iab_t iab = data;
|
|
|
0331fa |
+ int retval = error_status & ~(PAM_DATA_REPLACE|PAM_DATA_SILENT);
|
|
|
0331fa |
+
|
|
|
0331fa |
+ data = NULL;
|
|
|
0331fa |
+ if (error_status & PAM_DATA_REPLACE) {
|
|
|
0331fa |
+ goto done;
|
|
|
0331fa |
+ }
|
|
|
0331fa |
+
|
|
|
0331fa |
+ if (retval != PAM_SUCCESS || !(error_status & PAM_DATA_SILENT)) {
|
|
|
0331fa |
+ goto done;
|
|
|
0331fa |
+ }
|
|
|
0331fa |
+
|
|
|
0331fa |
+ if (cap_iab_set_proc(iab) != 0) {
|
|
|
0331fa |
+ D(("IAB setting failed"));
|
|
|
0331fa |
+ }
|
|
|
0331fa |
+
|
|
|
0331fa |
+done:
|
|
|
0331fa |
+ cap_free(iab);
|
|
|
0331fa |
+}
|
|
|
0331fa |
+
|
|
|
0331fa |
+/*
|
|
|
0331fa |
* Set capabilities for current process to match the current
|
|
|
0331fa |
* permitted+executable sets combined with the configured inheritable
|
|
|
0331fa |
* set.
|
|
|
0331fa |
@@ -230,12 +261,21 @@
|
|
|
0331fa |
goto cleanup_conf;
|
|
|
0331fa |
}
|
|
|
0331fa |
|
|
|
0331fa |
- if (!cap_iab_set_proc(iab)) {
|
|
|
0331fa |
+ if (cs->defer) {
|
|
|
0331fa |
+ D(("configured to delay applying IAB"));
|
|
|
0331fa |
+ pam_set_data(cs->pamh, "pam_cap_iab", iab, iab_apply);
|
|
|
0331fa |
+ iab = NULL;
|
|
|
0331fa |
+ } else if (!cap_iab_set_proc(iab)) {
|
|
|
0331fa |
D(("able to set the IAB [%s] value", conf_caps));
|
|
|
0331fa |
ok = 1;
|
|
|
0331fa |
}
|
|
|
0331fa |
cap_free(iab);
|
|
|
0331fa |
|
|
|
0331fa |
+ if (cs->keepcaps) {
|
|
|
0331fa |
+ D(("setting keepcaps"));
|
|
|
0331fa |
+ (void) cap_prctlw(PR_SET_KEEPCAPS, 1, 0, 0, 0, 0);
|
|
|
0331fa |
+ }
|
|
|
0331fa |
+
|
|
|
0331fa |
cleanup_conf:
|
|
|
0331fa |
memset(conf_caps, 0, conf_caps_length);
|
|
|
0331fa |
_pam_drop(conf_caps);
|
|
|
0331fa |
@@ -268,6 +308,10 @@
|
|
|
0331fa |
pcs->debug = 1;
|
|
|
0331fa |
} else if (!strncmp(*argv, "config=", 7)) {
|
|
|
0331fa |
pcs->conf_filename = 7 + *argv;
|
|
|
0331fa |
+ } else if (!strcmp(*argv, "keepcaps")) {
|
|
|
0331fa |
+ pcs->keepcaps = 1;
|
|
|
0331fa |
+ } else if (!strcmp(*argv, "defer")) {
|
|
|
0331fa |
+ pcs->defer = 1;
|
|
|
0331fa |
} else {
|
|
|
0331fa |
_pam_log(LOG_ERR, "unknown option; %s", *argv);
|
|
|
0331fa |
}
|
|
|
0331fa |
@@ -353,6 +397,7 @@
|
|
|
0331fa |
return PAM_AUTH_ERR;
|
|
|
0331fa |
}
|
|
|
0331fa |
|
|
|
0331fa |
+ pcs.pamh = pamh;
|
|
|
0331fa |
retval = set_capabilities(&pcs;;
|
|
|
0331fa |
memset(&pcs, 0, sizeof(pcs));
|
|
|
0331fa |
|