1157 lines
34 KiB
Diff
1157 lines
34 KiB
Diff
diff -up Linux-PAM-1.3.1/modules/pam_namespace/namespace.init.pam-namespace-rebase Linux-PAM-1.3.1/modules/pam_namespace/namespace.init
|
|
--- Linux-PAM-1.3.1/modules/pam_namespace/namespace.init.pam-namespace-rebase 2017-02-10 11:10:15.000000000 +0100
|
|
+++ Linux-PAM-1.3.1/modules/pam_namespace/namespace.init 2025-06-17 12:50:04.962542096 +0200
|
|
@@ -15,8 +15,8 @@ if [ "$3" = 1 ]; then
|
|
gid=$(echo "$passwd" | cut -f4 -d":")
|
|
cp -rT /etc/skel "$homedir"
|
|
chown -R "$user":"$gid" "$homedir"
|
|
- mask=$(awk '/^UMASK/{gsub("#.*$", "", $2); print $2; exit}' /etc/login.defs)
|
|
- mode=$(printf "%o" $((0777 & ~$mask)))
|
|
+ mask=$(sed -E -n 's/^UMASK[[:space:]]+([^#[:space:]]+).*/\1/p' /etc/login.defs)
|
|
+ mode=$(printf "%o" $((0777 & ~mask)))
|
|
chmod ${mode:-700} "$homedir"
|
|
[ -x /sbin/restorecon ] && /sbin/restorecon -R "$homedir"
|
|
fi
|
|
diff -up Linux-PAM-1.3.1/modules/pam_namespace/pam_namespace.c.pam-namespace-rebase Linux-PAM-1.3.1/modules/pam_namespace/pam_namespace.c
|
|
--- Linux-PAM-1.3.1/modules/pam_namespace/pam_namespace.c.pam-namespace-rebase 2025-06-17 12:50:04.954195973 +0200
|
|
+++ Linux-PAM-1.3.1/modules/pam_namespace/pam_namespace.c 2025-06-17 12:51:08.445616548 +0200
|
|
@@ -34,9 +34,250 @@
|
|
|
|
#define _ATFILE_SOURCE
|
|
|
|
+#include "config.h"
|
|
+#include <stdint.h>
|
|
+#include "pam_cc_compat.h"
|
|
+#include "pam_inline.h"
|
|
#include "pam_namespace.h"
|
|
#include "argv_parse.h"
|
|
|
|
+/* --- evaluating all files in VENDORDIR/security/namespace.d and /etc/security/namespace.d --- */
|
|
+static const char *base_name(const char *path)
|
|
+{
|
|
+ const char *base = strrchr(path, '/');
|
|
+ return base ? base+1 : path;
|
|
+}
|
|
+
|
|
+static int
|
|
+compare_filename(const void *a, const void *b)
|
|
+{
|
|
+ return strcmp(base_name(* (char * const *) a),
|
|
+ base_name(* (char * const *) b));
|
|
+}
|
|
+
|
|
+static void close_fds_pre_exec(struct instance_data *idata)
|
|
+{
|
|
+ if (pam_modutil_sanitize_helper_fds(idata->pamh, PAM_MODUTIL_IGNORE_FD,
|
|
+ PAM_MODUTIL_IGNORE_FD, PAM_MODUTIL_IGNORE_FD) < 0) {
|
|
+ _exit(1);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void
|
|
+strip_trailing_slashes(char *str)
|
|
+{
|
|
+ char *p = str + strlen(str);
|
|
+
|
|
+ while (--p > str && *p == '/')
|
|
+ *p = '\0';
|
|
+}
|
|
+
|
|
+static int protect_mount(int dfd, const char *path, struct instance_data *idata)
|
|
+{
|
|
+ struct protect_dir_s *dir = idata->protect_dirs;
|
|
+ char tmpbuf[64];
|
|
+
|
|
+ while (dir != NULL) {
|
|
+ if (strcmp(path, dir->dir) == 0) {
|
|
+ return 0;
|
|
+ }
|
|
+ dir = dir->next;
|
|
+ }
|
|
+
|
|
+ if (pam_sprintf(tmpbuf, "/proc/self/fd/%d", dfd) < 0)
|
|
+ return -1;
|
|
+
|
|
+ dir = calloc(1, sizeof(*dir));
|
|
+
|
|
+ if (dir == NULL) {
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ dir->dir = strdup(path);
|
|
+
|
|
+ if (dir->dir == NULL) {
|
|
+ free(dir);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ if (idata->flags & PAMNS_DEBUG) {
|
|
+ pam_syslog(idata->pamh, LOG_INFO,
|
|
+ "Protect mount of %s over itself", path);
|
|
+ }
|
|
+
|
|
+ if (mount(tmpbuf, tmpbuf, NULL, MS_BIND, NULL) != 0) {
|
|
+ int save_errno = errno;
|
|
+ pam_syslog(idata->pamh, LOG_ERR,
|
|
+ "Protect mount of %s failed: %m", tmpbuf);
|
|
+ free(dir->dir);
|
|
+ free(dir);
|
|
+ errno = save_errno;
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ dir->next = idata->protect_dirs;
|
|
+ idata->protect_dirs = dir;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int protect_dir(const char *path, mode_t mode, int do_mkdir,
|
|
+ struct instance_data *idata)
|
|
+{
|
|
+ char *p = strdup(path);
|
|
+ char *d;
|
|
+ char *dir = p;
|
|
+ int dfd = AT_FDCWD;
|
|
+ int dfd_next;
|
|
+ int save_errno;
|
|
+ int flags = O_RDONLY | O_DIRECTORY;
|
|
+ int rv = -1;
|
|
+ struct stat st;
|
|
+
|
|
+ if (p == NULL) {
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ if (*dir == '/') {
|
|
+ dfd = open("/", flags);
|
|
+ if (dfd == -1) {
|
|
+ goto error;
|
|
+ }
|
|
+ dir++; /* assume / is safe */
|
|
+ }
|
|
+
|
|
+ while ((d=strchr(dir, '/')) != NULL) {
|
|
+ *d = '\0';
|
|
+ dfd_next = openat(dfd, dir, flags);
|
|
+ if (dfd_next == -1) {
|
|
+ goto error;
|
|
+ }
|
|
+
|
|
+ if (dfd != AT_FDCWD)
|
|
+ close(dfd);
|
|
+ dfd = dfd_next;
|
|
+
|
|
+ if (fstat(dfd, &st) != 0) {
|
|
+ goto error;
|
|
+ }
|
|
+
|
|
+ if (flags & O_NOFOLLOW) {
|
|
+ /* we are inside user-owned dir - protect */
|
|
+ if (protect_mount(dfd, p, idata) == -1)
|
|
+ goto error;
|
|
+ } else if (st.st_uid != 0 || st.st_gid != 0 ||
|
|
+ (st.st_mode & S_IWOTH)) {
|
|
+ /* do not follow symlinks on subdirectories */
|
|
+ flags |= O_NOFOLLOW;
|
|
+ }
|
|
+
|
|
+ *d = '/';
|
|
+ dir = d + 1;
|
|
+ }
|
|
+
|
|
+ rv = openat(dfd, dir, flags);
|
|
+
|
|
+ if (rv == -1) {
|
|
+ if (!do_mkdir || mkdirat(dfd, dir, mode) != 0) {
|
|
+ goto error;
|
|
+ }
|
|
+ rv = openat(dfd, dir, flags);
|
|
+ }
|
|
+
|
|
+ if (flags & O_NOFOLLOW) {
|
|
+ /* we are inside user-owned dir - protect */
|
|
+ if (protect_mount(rv, p, idata) == -1) {
|
|
+ save_errno = errno;
|
|
+ close(rv);
|
|
+ rv = -1;
|
|
+ errno = save_errno;
|
|
+ }
|
|
+ }
|
|
+
|
|
+error:
|
|
+ save_errno = errno;
|
|
+ free(p);
|
|
+ if (dfd != AT_FDCWD && dfd >= 0)
|
|
+ close(dfd);
|
|
+ errno = save_errno;
|
|
+
|
|
+ return rv;
|
|
+}
|
|
+
|
|
+/* Evaluating a list of files which have to be parsed in the right order:
|
|
+ *
|
|
+ * - If etc/security/namespace.d/@filename@.conf exists, then
|
|
+ * %vendordir%/security/namespace.d/@filename@.conf should not be used.
|
|
+ * - All files in both namespace.d directories are sorted by their @filename@.conf in
|
|
+ * lexicographic order regardless of which of the directories they reside in. */
|
|
+static char **read_namespace_dir(struct instance_data *idata)
|
|
+{
|
|
+ glob_t globbuf;
|
|
+ size_t i=0;
|
|
+ int glob_rv = glob(NAMESPACE_D_GLOB, GLOB_ERR | GLOB_NOSORT, NULL, &globbuf);
|
|
+ char **file_list;
|
|
+ size_t file_list_size = glob_rv == 0 ? globbuf.gl_pathc : 0;
|
|
+
|
|
+#ifdef VENDOR_NAMESPACE_D_GLOB
|
|
+ glob_t globbuf_vendor;
|
|
+ int glob_rv_vendor = glob(VENDOR_NAMESPACE_D_GLOB, GLOB_ERR | GLOB_NOSORT, NULL, &globbuf_vendor);
|
|
+ if (glob_rv_vendor == 0)
|
|
+ file_list_size += globbuf_vendor.gl_pathc;
|
|
+#endif
|
|
+ file_list = malloc((file_list_size + 1) * sizeof(char*));
|
|
+ if (file_list == NULL) {
|
|
+ pam_syslog(idata->pamh, LOG_ERR, "Cannot allocate memory for file list: %m");
|
|
+#ifdef VENDOR_NAMESPACE_D_GLOB
|
|
+ if (glob_rv_vendor == 0)
|
|
+ globfree(&globbuf_vendor);
|
|
+#endif
|
|
+ if (glob_rv == 0)
|
|
+ globfree(&globbuf);
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ if (glob_rv == 0) {
|
|
+ for (i = 0; i < globbuf.gl_pathc; i++) {
|
|
+ file_list[i] = strdup(globbuf.gl_pathv[i]);
|
|
+ if (file_list[i] == NULL) {
|
|
+ pam_syslog(idata->pamh, LOG_ERR, "strdup failed: %m");
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+#ifdef VENDOR_NAMESPACE_D_GLOB
|
|
+ if (glob_rv_vendor == 0) {
|
|
+ for (size_t j = 0; j < globbuf_vendor.gl_pathc; j++) {
|
|
+ if (glob_rv == 0 && globbuf.gl_pathc > 0) {
|
|
+ int double_found = 0;
|
|
+ for (size_t k = 0; k < globbuf.gl_pathc; k++) {
|
|
+ if (strcmp(base_name(globbuf.gl_pathv[k]),
|
|
+ base_name(globbuf_vendor.gl_pathv[j])) == 0) {
|
|
+ double_found = 1;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ if (double_found)
|
|
+ continue;
|
|
+ }
|
|
+ file_list[i] = strdup(globbuf_vendor.gl_pathv[j]);
|
|
+ if (file_list[i] == NULL) {
|
|
+ pam_syslog(idata->pamh, LOG_ERR, "strdup failed: %m");
|
|
+ break;
|
|
+ }
|
|
+ i++;
|
|
+ }
|
|
+ globfree(&globbuf_vendor);
|
|
+ }
|
|
+#endif
|
|
+ file_list[i] = NULL;
|
|
+ qsort(file_list, i, sizeof(char *), compare_filename);
|
|
+ if (glob_rv == 0)
|
|
+ globfree(&globbuf);
|
|
+
|
|
+ return file_list;
|
|
+}
|
|
+
|
|
/*
|
|
* Adds an entry for a polyinstantiated directory to the linked list of
|
|
* polyinstantiated directories. It is called from process_line() while
|
|
@@ -106,7 +347,7 @@ static void cleanup_protect_data(pam_han
|
|
unprotect_dirs(data);
|
|
}
|
|
|
|
-static char *expand_variables(const char *orig, const char *var_names[], const char *var_values[])
|
|
+static char *expand_variables(const char *orig, const char *const var_names[], const char *var_values[])
|
|
{
|
|
const char *src = orig;
|
|
char *dst;
|
|
@@ -117,7 +358,7 @@ static char *expand_variables(const char
|
|
if (*src == '$') {
|
|
int i;
|
|
for (i = 0; var_names[i]; i++) {
|
|
- int namelen = strlen(var_names[i]);
|
|
+ size_t namelen = strlen(var_names[i]);
|
|
if (strncmp(var_names[i], src+1, namelen) == 0) {
|
|
dstlen += strlen(var_values[i]) - 1; /* $ */
|
|
src += namelen;
|
|
@@ -135,7 +376,7 @@ static char *expand_variables(const char
|
|
if (c == '$') {
|
|
int i;
|
|
for (i = 0; var_names[i]; i++) {
|
|
- int namelen = strlen(var_names[i]);
|
|
+ size_t namelen = strlen(var_names[i]);
|
|
if (strncmp(var_names[i], src+1, namelen) == 0) {
|
|
dst = stpcpy(dst, var_values[i]);
|
|
--dst;
|
|
@@ -219,8 +460,7 @@ static int parse_iscript_params(char *pa
|
|
|
|
if (*params != '\0') {
|
|
if (*params != '/') { /* path is relative to NAMESPACE_D_DIR */
|
|
- if (asprintf(&poly->init_script, "%s%s", NAMESPACE_D_DIR, params) == -1)
|
|
- return -1;
|
|
+ poly->init_script = pam_asprintf("%s%s", NAMESPACE_D_DIR, params);
|
|
} else {
|
|
poly->init_script = strdup(params);
|
|
}
|
|
@@ -259,7 +499,7 @@ static int filter_mntopts(const char *op
|
|
|
|
do {
|
|
size_t len;
|
|
- int i;
|
|
+ unsigned int i;
|
|
|
|
end = strchr(opts, ',');
|
|
if (end == NULL) {
|
|
@@ -268,7 +508,7 @@ static int filter_mntopts(const char *op
|
|
len = end - opts;
|
|
}
|
|
|
|
- for (i = 0; i < (int)(sizeof(mntflags)/sizeof(mntflags[0])); i++) {
|
|
+ for (i = 0; i < PAM_ARRAY_SIZE(mntflags); i++) {
|
|
if (mntflags[i].len != len)
|
|
continue;
|
|
if (memcmp(mntflags[i].name, opts, len) == 0) {
|
|
@@ -302,9 +542,9 @@ static int parse_method(char *method, st
|
|
{
|
|
enum polymethod pm;
|
|
char *sptr = NULL;
|
|
- static const char *method_names[] = { "user", "context", "level", "tmpdir",
|
|
+ static const char *const method_names[] = { "user", "context", "level", "tmpdir",
|
|
"tmpfs", NULL };
|
|
- static const char *flag_names[] = { "create", "noinit", "iscript",
|
|
+ static const char *const flag_names[] = { "create", "noinit", "iscript",
|
|
"shared", "mntopts", NULL };
|
|
static const unsigned int flag_values[] = { POLYDIR_CREATE, POLYDIR_NOINIT,
|
|
POLYDIR_ISCRIPT, POLYDIR_SHARED, POLYDIR_MNTOPTS };
|
|
@@ -329,7 +569,7 @@ static int parse_method(char *method, st
|
|
|
|
while ((flag=strtok_r(NULL, ":", &sptr)) != NULL) {
|
|
for (i = 0; flag_names[i]; i++) {
|
|
- int namelen = strlen(flag_names[i]);
|
|
+ size_t namelen = strlen(flag_names[i]);
|
|
|
|
if (strncmp(flag, flag_names[i], namelen) == 0) {
|
|
poly->flags |= flag_values[i];
|
|
@@ -375,27 +615,27 @@ static int parse_method(char *method, st
|
|
* of the namespace configuration file. It skips over comments and incomplete
|
|
* or malformed lines. It processes a valid line with information on
|
|
* polyinstantiating a directory by populating appropriate fields of a
|
|
- * polyinstatiated directory structure and then calling add_polydir_entry to
|
|
+ * polyinstantiated directory structure and then calling add_polydir_entry to
|
|
* add that entry to the linked list of polyinstantiated directories.
|
|
*/
|
|
static int process_line(char *line, const char *home, const char *rhome,
|
|
struct instance_data *idata)
|
|
{
|
|
char *dir = NULL, *instance_prefix = NULL, *rdir = NULL;
|
|
+ const char *config_dir, *config_instance_prefix;
|
|
char *method, *uids;
|
|
char *tptr;
|
|
struct polydir_s *poly;
|
|
int retval = 0;
|
|
char **config_options = NULL;
|
|
- static const char *var_names[] = {"HOME", "USER", NULL};
|
|
+ static const char *const var_names[] = {"HOME", "USER", NULL};
|
|
const char *var_values[] = {home, idata->user};
|
|
const char *rvar_values[] = {rhome, idata->ruser};
|
|
- int len;
|
|
|
|
/*
|
|
* skip the leading white space
|
|
*/
|
|
- while (*line && isspace(*line))
|
|
+ while (*line && isspace((unsigned char)*line))
|
|
line++;
|
|
|
|
/*
|
|
@@ -431,22 +671,19 @@ static int process_line(char *line, cons
|
|
goto erralloc;
|
|
}
|
|
|
|
- dir = config_options[0];
|
|
- if (dir == NULL) {
|
|
+ config_dir = config_options[0];
|
|
+ if (config_dir == NULL) {
|
|
pam_syslog(idata->pamh, LOG_NOTICE, "Invalid line missing polydir");
|
|
goto skipping;
|
|
}
|
|
- instance_prefix = config_options[1];
|
|
- if (instance_prefix == NULL) {
|
|
+ config_instance_prefix = config_options[1];
|
|
+ if (config_instance_prefix == NULL) {
|
|
pam_syslog(idata->pamh, LOG_NOTICE, "Invalid line missing instance_prefix");
|
|
- instance_prefix = NULL;
|
|
goto skipping;
|
|
}
|
|
method = config_options[2];
|
|
if (method == NULL) {
|
|
pam_syslog(idata->pamh, LOG_NOTICE, "Invalid line missing method");
|
|
- instance_prefix = NULL;
|
|
- dir = NULL;
|
|
goto skipping;
|
|
}
|
|
|
|
@@ -461,19 +698,16 @@ static int process_line(char *line, cons
|
|
/*
|
|
* Expand $HOME and $USER in poly dir and instance dir prefix
|
|
*/
|
|
- if ((rdir=expand_variables(dir, var_names, rvar_values)) == NULL) {
|
|
- instance_prefix = NULL;
|
|
- dir = NULL;
|
|
+ if ((rdir = expand_variables(config_dir, var_names, rvar_values)) == NULL) {
|
|
goto erralloc;
|
|
}
|
|
|
|
- if ((dir=expand_variables(dir, var_names, var_values)) == NULL) {
|
|
- instance_prefix = NULL;
|
|
+ if ((dir = expand_variables(config_dir, var_names, var_values)) == NULL) {
|
|
goto erralloc;
|
|
}
|
|
|
|
- if ((instance_prefix=expand_variables(instance_prefix, var_names, var_values))
|
|
- == NULL) {
|
|
+ if ((instance_prefix = expand_variables(config_instance_prefix,
|
|
+ var_names, var_values)) == NULL) {
|
|
goto erralloc;
|
|
}
|
|
|
|
@@ -483,15 +717,8 @@ static int process_line(char *line, cons
|
|
pam_syslog(idata->pamh, LOG_DEBUG, "Expanded instance prefix: '%s'", instance_prefix);
|
|
}
|
|
|
|
- len = strlen(dir);
|
|
- if (len > 0 && dir[len-1] == '/') {
|
|
- dir[len-1] = '\0';
|
|
- }
|
|
-
|
|
- len = strlen(rdir);
|
|
- if (len > 0 && rdir[len-1] == '/') {
|
|
- rdir[len-1] = '\0';
|
|
- }
|
|
+ strip_trailing_slashes(dir);
|
|
+ strip_trailing_slashes(rdir);
|
|
|
|
if (dir[0] == '\0' || rdir[0] == '\0') {
|
|
pam_syslog(idata->pamh, LOG_NOTICE, "Invalid polydir");
|
|
@@ -502,26 +729,19 @@ static int process_line(char *line, cons
|
|
* Populate polyinstantiated directory structure with appropriate
|
|
* pathnames and the method with which to polyinstantiate.
|
|
*/
|
|
- if (strlen(dir) >= sizeof(poly->dir)
|
|
- || strlen(rdir) >= sizeof(poly->rdir)
|
|
- || strlen(instance_prefix) >= sizeof(poly->instance_prefix)) {
|
|
- pam_syslog(idata->pamh, LOG_NOTICE, "Pathnames too long");
|
|
- goto skipping;
|
|
- }
|
|
- strcpy(poly->dir, dir);
|
|
- strcpy(poly->rdir, rdir);
|
|
- strcpy(poly->instance_prefix, instance_prefix);
|
|
-
|
|
if (parse_method(method, poly, idata) != 0) {
|
|
goto skipping;
|
|
}
|
|
|
|
- if (poly->method == TMPDIR) {
|
|
- if (sizeof(poly->instance_prefix) - strlen(poly->instance_prefix) < 7) {
|
|
- pam_syslog(idata->pamh, LOG_NOTICE, "Pathnames too long");
|
|
- goto skipping;
|
|
- }
|
|
- strcat(poly->instance_prefix, "XXXXXX");
|
|
+#define COPY_STR(dst, src, apd) \
|
|
+ pam_sprintf((dst), "%s%s", (src), (apd))
|
|
+
|
|
+ if (COPY_STR(poly->dir, dir, "") < 0
|
|
+ || COPY_STR(poly->rdir, rdir, "") < 0
|
|
+ || COPY_STR(poly->instance_prefix, instance_prefix,
|
|
+ poly->method == TMPDIR ? "XXXXXX" : "") < 0) {
|
|
+ pam_syslog(idata->pamh, LOG_NOTICE, "Pathnames too long");
|
|
+ goto skipping;
|
|
}
|
|
|
|
/*
|
|
@@ -545,7 +765,7 @@ static int process_line(char *line, cons
|
|
if (uids) {
|
|
uid_t *uidptr;
|
|
const char *ustr, *sstr;
|
|
- int count, i;
|
|
+ size_t count, i;
|
|
|
|
if (*uids == '~') {
|
|
poly->flags |= POLYDIR_EXCLUSIVE;
|
|
@@ -554,8 +774,13 @@ static int process_line(char *line, cons
|
|
for (count = 0, ustr = sstr = uids; sstr; ustr = sstr + 1, count++)
|
|
sstr = strchr(ustr, ',');
|
|
|
|
+ if (count > UINT_MAX || count > SIZE_MAX / sizeof(uid_t)) {
|
|
+ pam_syslog(idata->pamh, LOG_ERR, "Too many uids encountered in configuration");
|
|
+ goto skipping;
|
|
+ }
|
|
+
|
|
poly->num_uids = count;
|
|
- poly->uid = (uid_t *) malloc(count * sizeof (uid_t));
|
|
+ poly->uid = malloc(count * sizeof (uid_t));
|
|
uidptr = poly->uid;
|
|
if (uidptr == NULL) {
|
|
goto erralloc;
|
|
@@ -622,8 +847,6 @@ static int parse_config_file(struct inst
|
|
char *line;
|
|
int retval;
|
|
size_t len = 0;
|
|
- glob_t globbuf;
|
|
- const char *oldlocale;
|
|
size_t n;
|
|
|
|
/*
|
|
@@ -662,13 +885,16 @@ static int parse_config_file(struct inst
|
|
* process_line to process each line.
|
|
*/
|
|
|
|
- memset(&globbuf, '\0', sizeof(globbuf));
|
|
- oldlocale = setlocale(LC_COLLATE, "C");
|
|
- glob(NAMESPACE_D_GLOB, 0, NULL, &globbuf);
|
|
- if (oldlocale != NULL)
|
|
- setlocale(LC_COLLATE, oldlocale);
|
|
-
|
|
confname = PAM_NAMESPACE_CONFIG;
|
|
+#ifdef VENDOR_PAM_NAMESPACE_CONFIG
|
|
+ /* Check whether PAM_NAMESPACE_CONFIG file is available.
|
|
+ * If it does not exist, fall back to VENDOR_PAM_NAMESPACE_CONFIG file. */
|
|
+ struct stat buffer;
|
|
+ if (stat(confname, &buffer) != 0 && errno == ENOENT) {
|
|
+ confname = VENDOR_PAM_NAMESPACE_CONFIG;
|
|
+ }
|
|
+#endif
|
|
+ char **filename_list = read_namespace_dir(idata);
|
|
n = 0;
|
|
for (;;) {
|
|
if (idata->flags & PAMNS_DEBUG)
|
|
@@ -678,7 +904,6 @@ static int parse_config_file(struct inst
|
|
if (fil == NULL) {
|
|
pam_syslog(idata->pamh, LOG_ERR, "Error opening config file %s",
|
|
confname);
|
|
- globfree(&globbuf);
|
|
free(rhome);
|
|
free(home);
|
|
return PAM_SERVICE_ERR;
|
|
@@ -696,7 +921,6 @@ static int parse_config_file(struct inst
|
|
"Error processing conf file %s line %s", confname, line);
|
|
fclose(fil);
|
|
free(line);
|
|
- globfree(&globbuf);
|
|
free(rhome);
|
|
free(home);
|
|
return PAM_SERVICE_ERR;
|
|
@@ -705,14 +929,18 @@ static int parse_config_file(struct inst
|
|
fclose(fil);
|
|
free(line);
|
|
|
|
- if (n >= globbuf.gl_pathc)
|
|
+ if (filename_list == NULL || filename_list[n] == NULL)
|
|
break;
|
|
|
|
- confname = globbuf.gl_pathv[n];
|
|
- n++;
|
|
+ confname = filename_list[n++];
|
|
+ }
|
|
+
|
|
+ if (filename_list != NULL) {
|
|
+ for (size_t i = 0; filename_list[i] != NULL; i++)
|
|
+ free(filename_list[i]);
|
|
+ free(filename_list);
|
|
}
|
|
|
|
- globfree(&globbuf);
|
|
free(rhome);
|
|
free(home);
|
|
|
|
@@ -738,7 +966,7 @@ static int parse_config_file(struct inst
|
|
|
|
|
|
/*
|
|
- * This funtion returns true if a given uid is present in the polyinstantiated
|
|
+ * This function returns true if a given uid is present in the polyinstantiated
|
|
* directory's list of override uids. If the uid is one of the override
|
|
* uids for the polyinstantiated directory, polyinstantiation is not
|
|
* performed for that user for that directory.
|
|
@@ -795,11 +1023,11 @@ static char *md5hash(const char *instnam
|
|
|
|
#ifdef WITH_SELINUX
|
|
static int form_context(const struct polydir_s *polyptr,
|
|
- security_context_t *i_context, security_context_t *origcon,
|
|
+ char **i_context, char **origcon,
|
|
struct instance_data *idata)
|
|
{
|
|
int rc = PAM_SUCCESS;
|
|
- security_context_t scon = NULL;
|
|
+ char *scon = NULL;
|
|
security_class_t tclass;
|
|
|
|
/*
|
|
@@ -842,6 +1070,12 @@ static int form_context(const struct pol
|
|
|
|
if (polyptr->method == CONTEXT) {
|
|
tclass = string_to_security_class("dir");
|
|
+ if (tclass == 0) {
|
|
+ pam_syslog(idata->pamh, LOG_ERR,
|
|
+ "Error getting dir security class");
|
|
+ freecon(scon);
|
|
+ return PAM_SESSION_ERR;
|
|
+ }
|
|
|
|
if (security_compute_member(scon, *origcon, tclass,
|
|
i_context) < 0) {
|
|
@@ -878,7 +1112,7 @@ static int form_context(const struct pol
|
|
goto fail;
|
|
}
|
|
if (context_range_set(fcontext, context_range_get(scontext)) != 0) {
|
|
- pam_syslog(idata->pamh, LOG_ERR, "Unable to set MLS Componant of context");
|
|
+ pam_syslog(idata->pamh, LOG_ERR, "Unable to set MLS Component of context");
|
|
goto fail;
|
|
}
|
|
*i_context=strdup(context_str(fcontext));
|
|
@@ -895,6 +1129,7 @@ static int form_context(const struct pol
|
|
return rc;
|
|
}
|
|
/* Should never get here */
|
|
+ freecon(scon);
|
|
return PAM_SUCCESS;
|
|
}
|
|
#endif
|
|
@@ -908,7 +1143,7 @@ static int form_context(const struct pol
|
|
*/
|
|
#ifdef WITH_SELINUX
|
|
static int poly_name(const struct polydir_s *polyptr, char **i_name,
|
|
- security_context_t *i_context, security_context_t *origcon,
|
|
+ char **i_context, char **origcon,
|
|
struct instance_data *idata)
|
|
#else
|
|
static int poly_name(const struct polydir_s *polyptr, char **i_name,
|
|
@@ -919,7 +1154,7 @@ static int poly_name(const struct polydi
|
|
char *hash = NULL;
|
|
enum polymethod pm;
|
|
#ifdef WITH_SELINUX
|
|
- security_context_t rawcon = NULL;
|
|
+ char *rawcon = NULL;
|
|
#endif
|
|
|
|
*i_name = NULL;
|
|
@@ -956,10 +1191,8 @@ static int poly_name(const struct polydi
|
|
|
|
switch (pm) {
|
|
case USER:
|
|
- if (asprintf(i_name, "%s", idata->user) < 0) {
|
|
- *i_name = NULL;
|
|
+ if ((*i_name = strdup(idata->user)) == NULL)
|
|
goto fail;
|
|
- }
|
|
break;
|
|
|
|
#ifdef WITH_SELINUX
|
|
@@ -969,17 +1202,12 @@ static int poly_name(const struct polydi
|
|
pam_syslog(idata->pamh, LOG_ERR, "Error translating directory context");
|
|
goto fail;
|
|
}
|
|
- if (polyptr->flags & POLYDIR_SHARED) {
|
|
- if (asprintf(i_name, "%s", rawcon) < 0) {
|
|
- *i_name = NULL;
|
|
- goto fail;
|
|
- }
|
|
- } else {
|
|
- if (asprintf(i_name, "%s_%s", rawcon, idata->user) < 0) {
|
|
- *i_name = NULL;
|
|
- goto fail;
|
|
- }
|
|
- }
|
|
+ if (polyptr->flags & POLYDIR_SHARED)
|
|
+ *i_name = strdup(rawcon);
|
|
+ else
|
|
+ *i_name = pam_asprintf("%s_%s", rawcon, idata->user);
|
|
+ if (*i_name == NULL)
|
|
+ goto fail;
|
|
break;
|
|
|
|
#endif /* WITH_SELINUX */
|
|
@@ -1009,11 +1237,12 @@ static int poly_name(const struct polydi
|
|
*i_name = hash;
|
|
hash = NULL;
|
|
} else {
|
|
- char *newname;
|
|
- if (asprintf(&newname, "%.*s_%s", NAMESPACE_MAX_DIR_LEN-1-(int)strlen(hash),
|
|
- *i_name, hash) < 0) {
|
|
+ char *newname =
|
|
+ pam_asprintf("%.*s_%s",
|
|
+ NAMESPACE_MAX_DIR_LEN - 1 - (int)strlen(hash),
|
|
+ *i_name, hash);
|
|
+ if (newname == NULL)
|
|
goto fail;
|
|
- }
|
|
free(*i_name);
|
|
*i_name = newname;
|
|
}
|
|
@@ -1038,137 +1267,6 @@ fail:
|
|
return rc;
|
|
}
|
|
|
|
-static int protect_mount(int dfd, const char *path, struct instance_data *idata)
|
|
-{
|
|
- struct protect_dir_s *dir = idata->protect_dirs;
|
|
- char tmpbuf[64];
|
|
-
|
|
- while (dir != NULL) {
|
|
- if (strcmp(path, dir->dir) == 0) {
|
|
- return 0;
|
|
- }
|
|
- dir = dir->next;
|
|
- }
|
|
-
|
|
- dir = calloc(1, sizeof(*dir));
|
|
-
|
|
- if (dir == NULL) {
|
|
- return -1;
|
|
- }
|
|
-
|
|
- dir->dir = strdup(path);
|
|
-
|
|
- if (dir->dir == NULL) {
|
|
- free(dir);
|
|
- return -1;
|
|
- }
|
|
-
|
|
- snprintf(tmpbuf, sizeof(tmpbuf), "/proc/self/fd/%d", dfd);
|
|
-
|
|
- if (idata->flags & PAMNS_DEBUG) {
|
|
- pam_syslog(idata->pamh, LOG_INFO,
|
|
- "Protect mount of %s over itself", path);
|
|
- }
|
|
-
|
|
- if (mount(tmpbuf, tmpbuf, NULL, MS_BIND, NULL) != 0) {
|
|
- int save_errno = errno;
|
|
- pam_syslog(idata->pamh, LOG_ERR,
|
|
- "Protect mount of %s failed: %m", tmpbuf);
|
|
- free(dir->dir);
|
|
- free(dir);
|
|
- errno = save_errno;
|
|
- return -1;
|
|
- }
|
|
-
|
|
- dir->next = idata->protect_dirs;
|
|
- idata->protect_dirs = dir;
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static int protect_dir(const char *path, mode_t mode, int do_mkdir,
|
|
- struct instance_data *idata)
|
|
-{
|
|
- char *p = strdup(path);
|
|
- char *d;
|
|
- char *dir = p;
|
|
- int dfd = AT_FDCWD;
|
|
- int dfd_next;
|
|
- int save_errno;
|
|
- int flags = O_RDONLY | O_DIRECTORY;
|
|
- int rv = -1;
|
|
- struct stat st;
|
|
-
|
|
- if (p == NULL) {
|
|
- goto error;
|
|
- }
|
|
-
|
|
- if (*dir == '/') {
|
|
- dfd = open("/", flags);
|
|
- if (dfd == -1) {
|
|
- goto error;
|
|
- }
|
|
- dir++; /* assume / is safe */
|
|
- }
|
|
-
|
|
- while ((d=strchr(dir, '/')) != NULL) {
|
|
- *d = '\0';
|
|
- dfd_next = openat(dfd, dir, flags);
|
|
- if (dfd_next == -1) {
|
|
- goto error;
|
|
- }
|
|
-
|
|
- if (dfd != AT_FDCWD)
|
|
- close(dfd);
|
|
- dfd = dfd_next;
|
|
-
|
|
- if (fstat(dfd, &st) != 0) {
|
|
- goto error;
|
|
- }
|
|
-
|
|
- if (flags & O_NOFOLLOW) {
|
|
- /* we are inside user-owned dir - protect */
|
|
- if (protect_mount(dfd, p, idata) == -1)
|
|
- goto error;
|
|
- } else if (st.st_uid != 0 || st.st_gid != 0 ||
|
|
- (st.st_mode & S_IWOTH)) {
|
|
- /* do not follow symlinks on subdirectories */
|
|
- flags |= O_NOFOLLOW;
|
|
- }
|
|
-
|
|
- *d = '/';
|
|
- dir = d + 1;
|
|
- }
|
|
-
|
|
- rv = openat(dfd, dir, flags);
|
|
-
|
|
- if (rv == -1) {
|
|
- if (!do_mkdir || mkdirat(dfd, dir, mode) != 0) {
|
|
- goto error;
|
|
- }
|
|
- rv = openat(dfd, dir, flags);
|
|
- }
|
|
-
|
|
- if (flags & O_NOFOLLOW) {
|
|
- /* we are inside user-owned dir - protect */
|
|
- if (protect_mount(rv, p, idata) == -1) {
|
|
- save_errno = errno;
|
|
- close(rv);
|
|
- rv = -1;
|
|
- errno = save_errno;
|
|
- }
|
|
- }
|
|
-
|
|
-error:
|
|
- save_errno = errno;
|
|
- free(p);
|
|
- if (dfd != AT_FDCWD && dfd >= 0)
|
|
- close(dfd);
|
|
- errno = save_errno;
|
|
-
|
|
- return rv;
|
|
-}
|
|
-
|
|
static int check_inst_parent(char *ipath, struct instance_data *idata)
|
|
{
|
|
struct stat instpbuf;
|
|
@@ -1180,13 +1278,12 @@ static int check_inst_parent(char *ipath
|
|
* admin explicitly instructs to ignore the instance parent
|
|
* mode by the "ignore_instance_parent_mode" argument).
|
|
*/
|
|
- inst_parent = (char *) malloc(strlen(ipath)+1);
|
|
+ inst_parent = strdup(ipath);
|
|
if (!inst_parent) {
|
|
pam_syslog(idata->pamh, LOG_CRIT, "Error allocating pathname string");
|
|
return PAM_SESSION_ERR;
|
|
}
|
|
|
|
- strcpy(inst_parent, ipath);
|
|
trailing_slash = strrchr(inst_parent, '/');
|
|
if (trailing_slash)
|
|
*trailing_slash = '\0';
|
|
@@ -1226,72 +1323,83 @@ static int inst_init(const struct polydi
|
|
struct instance_data *idata, int newdir)
|
|
{
|
|
pid_t rc, pid;
|
|
- struct sigaction newsa, oldsa;
|
|
int status;
|
|
const char *init_script = NAMESPACE_INIT_SCRIPT;
|
|
|
|
+#ifdef VENDOR_NAMESPACE_INIT_SCRIPT
|
|
+ /* Check whether NAMESPACE_INIT_SCRIPT file is available.
|
|
+ * If it does not exist, fall back to VENDOR_NAMESPACE_INIT_SCRIPT file. */
|
|
+ struct stat buffer;
|
|
+ if (stat(init_script, &buffer) != 0 && errno == ENOENT) {
|
|
+ init_script = VENDOR_NAMESPACE_INIT_SCRIPT;
|
|
+ }
|
|
+#endif
|
|
+
|
|
+ if ((polyptr->flags & POLYDIR_ISCRIPT) && polyptr->init_script)
|
|
+ init_script = polyptr->init_script;
|
|
+
|
|
+ if (access(init_script, F_OK) != 0)
|
|
+ return PAM_SUCCESS;
|
|
+
|
|
+ if (access(init_script, X_OK) < 0) {
|
|
+ if (idata->flags & PAMNS_DEBUG)
|
|
+ pam_syslog(idata->pamh, LOG_ERR,
|
|
+ "Namespace init script not executable");
|
|
+ return PAM_SESSION_ERR;
|
|
+ }
|
|
+
|
|
+ struct sigaction newsa, oldsa;
|
|
+
|
|
memset(&newsa, '\0', sizeof(newsa));
|
|
- newsa.sa_handler = SIG_DFL;
|
|
+ newsa.sa_handler = SIG_DFL;
|
|
if (sigaction(SIGCHLD, &newsa, &oldsa) == -1) {
|
|
- pam_syslog(idata->pamh, LOG_ERR, "Cannot set signal value");
|
|
+ pam_syslog(idata->pamh, LOG_ERR, "failed to reset SIGCHLD handler");
|
|
return PAM_SESSION_ERR;
|
|
}
|
|
|
|
- if ((polyptr->flags & POLYDIR_ISCRIPT) && polyptr->init_script)
|
|
- init_script = polyptr->init_script;
|
|
+ pid = fork();
|
|
+ if (pid == 0) {
|
|
+ static char *envp[] = { NULL };
|
|
+#ifdef WITH_SELINUX
|
|
+ if (idata->flags & PAMNS_SELINUX_ENABLED) {
|
|
+ if (setexeccon(NULL) < 0)
|
|
+ _exit(1);
|
|
+ }
|
|
+#endif
|
|
+ /* Pass maximum privs when we exec() */
|
|
+ if (setuid(geteuid()) < 0) {
|
|
+ /* ignore failures, they don't matter */
|
|
+ }
|
|
|
|
- if (access(init_script, F_OK) == 0) {
|
|
- if (access(init_script, X_OK) < 0) {
|
|
- if (idata->flags & PAMNS_DEBUG)
|
|
- pam_syslog(idata->pamh, LOG_ERR,
|
|
- "Namespace init script not executable");
|
|
+ close_fds_pre_exec(idata);
|
|
+
|
|
+ execle(init_script, init_script,
|
|
+ polyptr->dir, ipath, newdir?"1":"0", idata->user, NULL, envp);
|
|
+ _exit(1);
|
|
+ } else if (pid > 0) {
|
|
+ while (((rc = waitpid(pid, &status, 0)) == (pid_t)-1) &&
|
|
+ (errno == EINTR));
|
|
+ if (rc == (pid_t)-1) {
|
|
+ pam_syslog(idata->pamh, LOG_ERR, "waitpid failed- %m");
|
|
+ rc = PAM_SESSION_ERR;
|
|
+ goto out;
|
|
+ }
|
|
+ if (!WIFEXITED(status) || WIFSIGNALED(status) > 0) {
|
|
+ pam_syslog(idata->pamh, LOG_ERR,
|
|
+ "Error initializing instance");
|
|
rc = PAM_SESSION_ERR;
|
|
goto out;
|
|
- } else {
|
|
- pid = fork();
|
|
- if (pid == 0) {
|
|
- static char *envp[] = { NULL };
|
|
-#ifdef WITH_SELINUX
|
|
- if (idata->flags & PAMNS_SELINUX_ENABLED) {
|
|
- if (setexeccon(NULL) < 0)
|
|
- _exit(1);
|
|
- }
|
|
-#endif
|
|
- /* Pass maximum privs when we exec() */
|
|
- if (setuid(geteuid()) < 0) {
|
|
- /* ignore failures, they don't matter */
|
|
- }
|
|
-
|
|
- if (execle(init_script, init_script,
|
|
- polyptr->dir, ipath, newdir?"1":"0", idata->user, NULL, envp) < 0)
|
|
- _exit(1);
|
|
- } else if (pid > 0) {
|
|
- while (((rc = waitpid(pid, &status, 0)) == (pid_t)-1) &&
|
|
- (errno == EINTR));
|
|
- if (rc == (pid_t)-1) {
|
|
- pam_syslog(idata->pamh, LOG_ERR, "waitpid failed- %m");
|
|
- rc = PAM_SESSION_ERR;
|
|
- goto out;
|
|
- }
|
|
- if (!WIFEXITED(status) || WIFSIGNALED(status) > 0) {
|
|
- pam_syslog(idata->pamh, LOG_ERR,
|
|
- "Error initializing instance");
|
|
- rc = PAM_SESSION_ERR;
|
|
- goto out;
|
|
- }
|
|
- } else if (pid < 0) {
|
|
- pam_syslog(idata->pamh, LOG_ERR,
|
|
- "Cannot fork to run namespace init script, %m");
|
|
- rc = PAM_SESSION_ERR;
|
|
- goto out;
|
|
- }
|
|
}
|
|
+ } else if (pid < 0) {
|
|
+ pam_syslog(idata->pamh, LOG_ERR,
|
|
+ "Cannot fork to run namespace init script, %m");
|
|
+ rc = PAM_SESSION_ERR;
|
|
+ goto out;
|
|
}
|
|
rc = PAM_SUCCESS;
|
|
out:
|
|
- (void) sigaction(SIGCHLD, &oldsa, NULL);
|
|
-
|
|
- return rc;
|
|
+ (void) sigaction(SIGCHLD, &oldsa, NULL);
|
|
+ return rc;
|
|
}
|
|
|
|
static int create_polydir(struct polydir_s *polyptr,
|
|
@@ -1395,7 +1503,7 @@ static int create_polydir(struct polydir
|
|
*/
|
|
#ifdef WITH_SELINUX
|
|
static int create_instance(struct polydir_s *polyptr, char *ipath, struct stat *statbuf,
|
|
- security_context_t icontext, security_context_t ocontext,
|
|
+ const char *icontext, const char *ocontext,
|
|
struct instance_data *idata)
|
|
#else
|
|
static int create_instance(struct polydir_s *polyptr, char *ipath, struct stat *statbuf,
|
|
@@ -1513,7 +1621,7 @@ static int ns_setup(struct polydir_s *po
|
|
char *instname = NULL;
|
|
struct stat statbuf;
|
|
#ifdef WITH_SELINUX
|
|
- security_context_t instcontext = NULL, origcontext = NULL;
|
|
+ char *instcontext = NULL, *origcontext = NULL;
|
|
#endif
|
|
|
|
if (idata->flags & PAMNS_DEBUG)
|
|
@@ -1522,16 +1630,14 @@ static int ns_setup(struct polydir_s *po
|
|
|
|
retval = protect_dir(polyptr->dir, 0, 0, idata);
|
|
|
|
- if (retval < 0 && errno != ENOENT) {
|
|
- pam_syslog(idata->pamh, LOG_ERR, "Polydir %s access error: %m",
|
|
- polyptr->dir);
|
|
- return PAM_SESSION_ERR;
|
|
- }
|
|
-
|
|
if (retval < 0) {
|
|
- if ((polyptr->flags & POLYDIR_CREATE) &&
|
|
- create_polydir(polyptr, idata) != PAM_SUCCESS)
|
|
- return PAM_SESSION_ERR;
|
|
+ if (errno != ENOENT || !(polyptr->flags & POLYDIR_CREATE)) {
|
|
+ pam_syslog(idata->pamh, LOG_ERR, "Polydir %s access error: %m",
|
|
+ polyptr->dir);
|
|
+ return PAM_SESSION_ERR;
|
|
+ }
|
|
+ if (create_polydir(polyptr, idata) != PAM_SUCCESS)
|
|
+ return PAM_SESSION_ERR;
|
|
} else {
|
|
close(retval);
|
|
}
|
|
@@ -1580,7 +1686,7 @@ static int ns_setup(struct polydir_s *po
|
|
#endif
|
|
}
|
|
|
|
- if (asprintf(&inst_dir, "%s%s", polyptr->instance_prefix, instname) < 0)
|
|
+ if ((inst_dir = pam_asprintf("%s%s", polyptr->instance_prefix, instname)) == NULL)
|
|
goto error_out;
|
|
|
|
if (idata->flags & PAMNS_DEBUG)
|
|
@@ -1692,8 +1798,9 @@ static int cleanup_tmpdirs(struct instan
|
|
_exit(1);
|
|
}
|
|
#endif
|
|
- if (execle("/bin/rm", "/bin/rm", "-rf", pptr->instance_prefix, NULL, envp) < 0)
|
|
- _exit(1);
|
|
+ close_fds_pre_exec(idata);
|
|
+ execle("/bin/rm", "/bin/rm", "-rf", pptr->instance_prefix, NULL, envp);
|
|
+ _exit(1);
|
|
} else if (pid > 0) {
|
|
while (((rc = waitpid(pid, &status, 0)) == (pid_t)-1) &&
|
|
(errno == EINTR));
|
|
@@ -1708,7 +1815,7 @@ static int cleanup_tmpdirs(struct instan
|
|
}
|
|
} else if (pid < 0) {
|
|
pam_syslog(idata->pamh, LOG_ERR,
|
|
- "Cannot fork to run namespace init script, %m");
|
|
+ "Cannot fork to cleanup temporary directory, %m");
|
|
rc = PAM_SESSION_ERR;
|
|
goto out;
|
|
}
|
|
@@ -1948,7 +2055,7 @@ static int orig_namespace(struct instanc
|
|
*/
|
|
static int ctxt_based_inst_needed(void)
|
|
{
|
|
- security_context_t scon = NULL;
|
|
+ char *scon = NULL;
|
|
int rc = 0;
|
|
|
|
rc = getexeccon(&scon);
|
|
@@ -1994,7 +2101,7 @@ static int root_shared(void)
|
|
break;
|
|
|
|
if (i == 6) {
|
|
- if (strncmp(tok, "shared:", 7) == 0)
|
|
+ if (pam_str_skip_prefix(tok, "shared:") != NULL)
|
|
/* there might be more / mounts, the last one counts */
|
|
rv = 1;
|
|
else
|
|
@@ -2162,7 +2269,7 @@ int pam_sm_close_session(pam_handle_t *p
|
|
{
|
|
int i, retval;
|
|
struct instance_data idata;
|
|
- void *polyptr;
|
|
+ const void *polyptr;
|
|
|
|
/* init instance data */
|
|
idata.flags = 0;
|
|
@@ -2202,7 +2309,7 @@ int pam_sm_close_session(pam_handle_t *p
|
|
pam_set_data(idata.pamh, NAMESPACE_PROTECT_DATA, NULL, NULL);
|
|
|
|
if (idata.flags & PAMNS_DEBUG)
|
|
- pam_syslog(idata.pamh, LOG_DEBUG, "close_session - sucessful");
|
|
+ pam_syslog(idata.pamh, LOG_DEBUG, "close_session - successful");
|
|
return PAM_SUCCESS;
|
|
}
|
|
|
|
@@ -2210,12 +2317,14 @@ int pam_sm_close_session(pam_handle_t *p
|
|
if (retval != PAM_SUCCESS)
|
|
return retval;
|
|
|
|
- retval = pam_get_data(idata.pamh, NAMESPACE_POLYDIR_DATA, (const void **)&polyptr);
|
|
+ retval = pam_get_data(idata.pamh, NAMESPACE_POLYDIR_DATA, &polyptr);
|
|
if (retval != PAM_SUCCESS || polyptr == NULL)
|
|
/* nothing to reset */
|
|
return PAM_SUCCESS;
|
|
|
|
- idata.polydirs_ptr = polyptr;
|
|
+ DIAG_PUSH_IGNORE_CAST_QUAL;
|
|
+ idata.polydirs_ptr = (void *)polyptr;
|
|
+ DIAG_POP_IGNORE_CAST_QUAL;
|
|
|
|
if (idata.flags & PAMNS_DEBUG)
|
|
pam_syslog(idata.pamh, LOG_DEBUG, "Resetting namespace for pid %d",
|
|
diff -up Linux-PAM-1.3.1/modules/pam_namespace/pam_namespace.h.pam-namespace-rebase Linux-PAM-1.3.1/modules/pam_namespace/pam_namespace.h
|
|
--- Linux-PAM-1.3.1/modules/pam_namespace/pam_namespace.h.pam-namespace-rebase 2025-06-17 12:50:04.921165460 +0200
|
|
+++ Linux-PAM-1.3.1/modules/pam_namespace/pam_namespace.h 2025-06-17 12:50:04.963237346 +0200
|
|
@@ -30,7 +30,7 @@
|
|
* DEALINGS IN THE SOFTWARE.
|
|
*/
|
|
|
|
-#if !(defined(linux))
|
|
+#ifndef __linux__
|
|
#error THIS CODE IS KNOWN TO WORK ONLY ON LINUX !!!
|
|
#endif
|
|
|
|
@@ -44,21 +44,16 @@
|
|
#include <stdlib.h>
|
|
#include <errno.h>
|
|
#include <syslog.h>
|
|
-#include <dlfcn.h>
|
|
-#include <stdarg.h>
|
|
#include <pwd.h>
|
|
#include <grp.h>
|
|
#include <limits.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
-#include <sys/resource.h>
|
|
#include <sys/mount.h>
|
|
#include <sys/wait.h>
|
|
-#include <libgen.h>
|
|
#include <fcntl.h>
|
|
#include <sched.h>
|
|
#include <glob.h>
|
|
-#include <locale.h>
|
|
#include "security/pam_modules.h"
|
|
#include "security/pam_modutil.h"
|
|
#include "security/pam_ext.h"
|
|
@@ -111,7 +106,7 @@
|
|
#define PAMNS_MOUNT_PRIVATE 0x00080000 /* Make the polydir mounts private */
|
|
|
|
/* polydir flags */
|
|
-#define POLYDIR_EXCLUSIVE 0x00000001 /* polyinstatiate exclusively for override uids */
|
|
+#define POLYDIR_EXCLUSIVE 0x00000001 /* polyinstantiate exclusively for override uids */
|
|
#define POLYDIR_CREATE 0x00000002 /* create the polydir */
|
|
#define POLYDIR_NOINIT 0x00000004 /* no init script */
|
|
#define POLYDIR_SHARED 0x00000008 /* share context/level instances among users */
|