Complete Yocto mirror with license table for TQMa6UL (2038-compliance)
- 264 license table entries with exact download URLs (224/264 resolved) - Complete sources/ directory with all BitBake recipes - Build configuration: tqma6ul-multi-mba6ulx, spaetzle (musl) - Full traceability for Softwarefreigabeantrag - GCC 13.4.0, Linux 6.6.102, U-Boot 2023.04, musl 1.2.4 - License distribution: GPL-2.0 (24), MIT (23), GPL-2.0+ (18), BSD-3 (16)
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
From 9b96fcfa5748934b8b6a4db4ee25a5e3165905c0 Mon Sep 17 00:00:00 2001
|
||||
From: Khem Raj <raj.khem@gmail.com>
|
||||
Date: Sat, 1 Jul 2023 07:48:17 -0700
|
||||
Subject: [PATCH] examples: Replace use of termio.h with termios.h
|
||||
|
||||
Fixes build with musl and makes it portable
|
||||
|
||||
Upstream-Status: Backport [https://github.com/linux-pam/linux-pam/commit/5374f677e4cae669eb9accf2449178b602e8a40a]
|
||||
Signed-off-by: Khem Raj <raj.khem@gmail.com>
|
||||
---
|
||||
examples/tty_conv.c | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/examples/tty_conv.c b/examples/tty_conv.c
|
||||
index 23f0684..db22500 100644
|
||||
--- a/examples/tty_conv.c
|
||||
+++ b/examples/tty_conv.c
|
||||
@@ -6,7 +6,8 @@
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
-#include <termio.h>
|
||||
+#include <termios.h>
|
||||
+#include <sys/ioctl.h>
|
||||
#include <security/pam_appl.h>
|
||||
|
||||
/***************************************
|
||||
@@ -16,7 +17,7 @@
|
||||
***************************************/
|
||||
static void echoOff(int fd, int off)
|
||||
{
|
||||
- struct termio tty;
|
||||
+ struct termios tty;
|
||||
if (ioctl(fd, TCGETA, &tty) < 0)
|
||||
{
|
||||
fprintf(stderr, "TCGETA failed: %s\n", strerror(errno));
|
||||
--
|
||||
2.41.0
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
From 10b80543807e3fc5af5f8bcfd8bb6e219bb3cecc Mon Sep 17 00:00:00 2001
|
||||
From: "Dmitry V. Levin" <ldv@strace.io>
|
||||
Date: Tue, 18 Feb 2025 08:00:00 +0000
|
||||
Subject: [PATCH] pam_inline: introduce pam_asprintf(), pam_snprintf(), and
|
||||
pam_sprintf()
|
||||
|
||||
pam_asprintf() is essentially asprintf() with the following semantic
|
||||
difference: it returns the string itself instead of its length.
|
||||
|
||||
pam_snprintf() is essentially snprintf() with the following semantic
|
||||
difference: it returns -1 in case of truncation.
|
||||
|
||||
pam_sprintf() is essentially snprintf() but with a check that the buffer
|
||||
is an array, and with an automatically calculated buffer size.
|
||||
|
||||
Use of these helpers would make error checking simpler.
|
||||
|
||||
(cherry picked from commit 10b80543807e3fc5af5f8bcfd8bb6e219bb3cecc)
|
||||
Signed-off-by: Dmitry V. Levin <ldv@strace.io>
|
||||
|
||||
Upstream-Status: Backport [https://github.com/linux-pam/linux-pam/commit/10b80543807e3fc5af5f8bcfd8bb6e219bb3cecc]
|
||||
Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
|
||||
---
|
||||
libpam/include/pam_cc_compat.h | 6 ++++++
|
||||
libpam/include/pam_inline.h | 36 ++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 42 insertions(+)
|
||||
|
||||
diff --git a/libpam/include/pam_cc_compat.h b/libpam/include/pam_cc_compat.h
|
||||
index 0a6e32d..af05428 100644
|
||||
--- a/libpam/include/pam_cc_compat.h
|
||||
+++ b/libpam/include/pam_cc_compat.h
|
||||
@@ -21,6 +21,12 @@
|
||||
# define PAM_ATTRIBUTE_ALIGNED(arg) /* empty */
|
||||
#endif
|
||||
|
||||
+#if PAM_GNUC_PREREQ(3, 0)
|
||||
+# define PAM_ATTRIBUTE_MALLOC __attribute__((__malloc__))
|
||||
+#else
|
||||
+# define PAM_ATTRIBUTE_MALLOC /* empty */
|
||||
+#endif
|
||||
+
|
||||
#if PAM_GNUC_PREREQ(4, 6)
|
||||
# define DIAG_PUSH_IGNORE_CAST_QUAL \
|
||||
_Pragma("GCC diagnostic push"); \
|
||||
diff --git a/libpam/include/pam_inline.h b/libpam/include/pam_inline.h
|
||||
index 7721c0b..ec0497c 100644
|
||||
--- a/libpam/include/pam_inline.h
|
||||
+++ b/libpam/include/pam_inline.h
|
||||
@@ -9,6 +9,8 @@
|
||||
#define PAM_INLINE_H
|
||||
|
||||
#include "pam_cc_compat.h"
|
||||
+#include <stdarg.h>
|
||||
+#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
@@ -126,6 +128,40 @@ pam_drop_response(struct pam_response *reply, int replies)
|
||||
}
|
||||
|
||||
|
||||
+static inline char * PAM_FORMAT((printf, 1, 2)) PAM_NONNULL((1)) PAM_ATTRIBUTE_MALLOC
|
||||
+pam_asprintf(const char *fmt, ...)
|
||||
+{
|
||||
+ int rc;
|
||||
+ char *res;
|
||||
+ va_list ap;
|
||||
+
|
||||
+ va_start(ap, fmt);
|
||||
+ rc = vasprintf(&res, fmt, ap);
|
||||
+ va_end(ap);
|
||||
+
|
||||
+ return rc < 0 ? NULL : res;
|
||||
+}
|
||||
+
|
||||
+static inline int PAM_FORMAT((printf, 3, 4)) PAM_NONNULL((3))
|
||||
+pam_snprintf(char *str, size_t size, const char *fmt, ...)
|
||||
+{
|
||||
+ int rc;
|
||||
+ va_list ap;
|
||||
+
|
||||
+ va_start(ap, fmt);
|
||||
+ rc = vsnprintf(str, size, fmt, ap);
|
||||
+ va_end(ap);
|
||||
+
|
||||
+ if (rc < 0 || (unsigned int) rc >= size)
|
||||
+ return -1;
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+#define pam_sprintf(str_, fmt_, ...) \
|
||||
+ pam_snprintf((str_), sizeof(str_) + PAM_MUST_BE_ARRAY(str_), (fmt_), \
|
||||
+ ##__VA_ARGS__)
|
||||
+
|
||||
+
|
||||
static inline int
|
||||
pam_read_passwords(int fd, int npass, char **passwords)
|
||||
{
|
||||
--
|
||||
2.49.0
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
From cc9d40b7cdbd3e15ccaa324a0dda1680ef9dea13 Mon Sep 17 00:00:00 2001
|
||||
From: Jacob Heider <jacob@pkgx.dev>
|
||||
Date: Wed, 17 Jan 2024 11:49:26 -0500
|
||||
Subject: [PATCH] pam_namespace: include stdint.h
|
||||
|
||||
pam_namespace.c makes use of SIZE_MAX but doesn't include stdint.h,
|
||||
resulting in the following build failures on 1.6.0:
|
||||
|
||||
pam_namespace.c: In function 'process_line':
|
||||
pam_namespace.c:649:41: error: 'SIZE_MAX' undeclared (first use in this function)
|
||||
649 | if (count > UINT_MAX || count > SIZE_MAX / sizeof(uid_t)) {
|
||||
| ^~~~~~~~
|
||||
pam_namespace.c:41:1: note: 'SIZE_MAX' is defined in header '<stdint.h>'; did you forget to '#include <stdint.h>'?
|
||||
40 | #include "argv_parse.h"
|
||||
+++ |+#include <stdint.h>
|
||||
41 |
|
||||
pam_namespace.c:649:41: note: each undeclared identifier is reported only once for each function it appears in
|
||||
649 | if (count > UINT_MAX || count > SIZE_MAX / sizeof(uid_t)) {
|
||||
| ^~~~~~~~
|
||||
|
||||
Fixes: v1.6.0~100 ("pam_namespace: validate amount of uids in config")
|
||||
Resolves: https://github.com/linux-pam/linux-pam/issues/733
|
||||
|
||||
Upstream-Status: Backport [https://github.com/linux-pam/linux-pam/commit/cc9d40b7cdbd3e15ccaa324a0dda1680ef9dea13]
|
||||
Signed-off-by: Khem Raj <raj.khem@gmail.com>
|
||||
---
|
||||
modules/pam_namespace/pam_namespace.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/modules/pam_namespace/pam_namespace.c b/modules/pam_namespace/pam_namespace.c
|
||||
index f72d67189..b16731c22 100644
|
||||
--- a/modules/pam_namespace/pam_namespace.c
|
||||
+++ b/modules/pam_namespace/pam_namespace.c
|
||||
@@ -34,6 +34,8 @@
|
||||
|
||||
#define _ATFILE_SOURCE
|
||||
|
||||
+#include "config.h"
|
||||
+#include <stdint.h>
|
||||
#include "pam_cc_compat.h"
|
||||
#include "pam_inline.h"
|
||||
#include "pam_namespace.h"
|
||||
@@ -0,0 +1,69 @@
|
||||
From 80dc2d410595b5193d32f965185710df27f3984e Mon Sep 17 00:00:00 2001
|
||||
From: Md Zain Hasib <hasibm@vmware.com>
|
||||
Date: Sat, 29 Jul 2023 11:01:35 +0530
|
||||
Subject: [PATCH] pam_pwhistory: fix passing NULL filename argument to
|
||||
pwhistory helper
|
||||
|
||||
This change fixes a bug when pwhistory_helper is invoked from
|
||||
pam_pwhistory with an NULL filename, pwhistory_helper receives a short
|
||||
circuited argc count of 3, ignoring the rest of the arguments passed
|
||||
due to filename being NULL. To resolve the issue, an empty string is
|
||||
passed in case the filename is empty, which is later changed back to
|
||||
NULL in pwhistory_helper so that it can be passed to opasswd to read
|
||||
the default opasswd file.
|
||||
|
||||
* modules/pam_pwhistory/pam_pwhistory.c (run_save_helper,
|
||||
run_check_helper): Replace NULL filename argument with an empty string.
|
||||
* modules/pam_pwhistory/pwhistory_helper.c (main): Replace empty string
|
||||
filename argument with NULL.
|
||||
|
||||
Fixes: 11c35109a67f ("pam_pwhistory: Enable alternate location for password history file (#396)")
|
||||
Signed-off-by: Dmitry V. Levin <ldv@strace.io>
|
||||
|
||||
Upstream-Status: Backport
|
||||
[https://github.com/linux-pam/linux-pam/commit/80dc2d410595b5193d32f965185710df27f3984e]
|
||||
|
||||
Signed-off-by: Yi Zhao <yi.zhao@windriver.com>
|
||||
---
|
||||
modules/pam_pwhistory/pam_pwhistory.c | 4 ++--
|
||||
modules/pam_pwhistory/pwhistory_helper.c | 2 +-
|
||||
2 files changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/modules/pam_pwhistory/pam_pwhistory.c b/modules/pam_pwhistory/pam_pwhistory.c
|
||||
index 5a7fb811..98ddffce 100644
|
||||
--- a/modules/pam_pwhistory/pam_pwhistory.c
|
||||
+++ b/modules/pam_pwhistory/pam_pwhistory.c
|
||||
@@ -141,7 +141,7 @@ run_save_helper(pam_handle_t *pamh, const char *user,
|
||||
args[0] = (char *)PWHISTORY_HELPER;
|
||||
args[1] = (char *)"save";
|
||||
args[2] = (char *)user;
|
||||
- args[3] = (char *)filename;
|
||||
+ args[3] = (char *)((filename != NULL) ? filename : "");
|
||||
DIAG_POP_IGNORE_CAST_QUAL;
|
||||
if (asprintf(&args[4], "%d", howmany) < 0 ||
|
||||
asprintf(&args[5], "%d", debug) < 0)
|
||||
@@ -228,7 +228,7 @@ run_check_helper(pam_handle_t *pamh, const char *user,
|
||||
args[0] = (char *)PWHISTORY_HELPER;
|
||||
args[1] = (char *)"check";
|
||||
args[2] = (char *)user;
|
||||
- args[3] = (char *)filename;
|
||||
+ args[3] = (char *)((filename != NULL) ? filename : "");
|
||||
DIAG_POP_IGNORE_CAST_QUAL;
|
||||
if (asprintf(&args[4], "%d", debug) < 0)
|
||||
{
|
||||
diff --git a/modules/pam_pwhistory/pwhistory_helper.c b/modules/pam_pwhistory/pwhistory_helper.c
|
||||
index 469d95fa..fb9a1e31 100644
|
||||
--- a/modules/pam_pwhistory/pwhistory_helper.c
|
||||
+++ b/modules/pam_pwhistory/pwhistory_helper.c
|
||||
@@ -108,7 +108,7 @@ main(int argc, char *argv[])
|
||||
|
||||
option = argv[1];
|
||||
user = argv[2];
|
||||
- filename = argv[3];
|
||||
+ filename = (argv[3][0] != '\0') ? argv[3] : NULL;
|
||||
|
||||
if (strcmp(option, "check") == 0 && argc == 5)
|
||||
return check_history(user, filename, argv[4]);
|
||||
--
|
||||
2.25.1
|
||||
|
||||
@@ -0,0 +1,750 @@
|
||||
From df1dab1a1a7900650ad4be157fea1a002048cc49 Mon Sep 17 00:00:00 2001
|
||||
From: Olivier Bal-Petre <olivier.bal-petre@ssi.gouv.fr>
|
||||
Date: Tue, 4 Mar 2025 14:37:02 +0100
|
||||
Subject: [PATCH ] pam-namespace-rebase
|
||||
|
||||
Refresh the pam-namespace.
|
||||
|
||||
Upstream-Status: Backport [https://github.com/linux-pam/linux-pam/commit/a8b4dce7b53d73de372e150028c970ee0a2a2e97]
|
||||
Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
|
||||
---
|
||||
modules/pam_namespace/pam_namespace.c | 444 +++++++++++++-------------
|
||||
modules/pam_namespace/pam_namespace.h | 7 +-
|
||||
2 files changed, 224 insertions(+), 227 deletions(-)
|
||||
|
||||
diff --git a/modules/pam_namespace/pam_namespace.c b/modules/pam_namespace/pam_namespace.c
|
||||
index b026861..166bfce 100644
|
||||
--- a/modules/pam_namespace/pam_namespace.c
|
||||
+++ b/modules/pam_namespace/pam_namespace.c
|
||||
@@ -41,7 +41,7 @@
|
||||
#include "pam_namespace.h"
|
||||
#include "argv_parse.h"
|
||||
|
||||
-/* --- evaluting all files in VENDORDIR/security/namespace.d and /etc/security/namespace.d --- */
|
||||
+/* --- 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, '/');
|
||||
@@ -55,6 +55,155 @@ compare_filename(const void *a, const void *b)
|
||||
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
|
||||
@@ -129,6 +278,7 @@ static char **read_namespace_dir(struct instance_data *idata)
|
||||
return file_list;
|
||||
}
|
||||
|
||||
+
|
||||
/*
|
||||
* Adds an entry for a polyinstantiated directory to the linked list of
|
||||
* polyinstantiated directories. It is called from process_line() while
|
||||
@@ -198,7 +348,7 @@ static void cleanup_protect_data(pam_handle_t *pamh UNUSED , void *data, int err
|
||||
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;
|
||||
@@ -209,7 +359,7 @@ static char *expand_variables(const char *orig, const char *var_names[], const c
|
||||
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;
|
||||
@@ -227,7 +377,7 @@ static char *expand_variables(const char *orig, const char *var_names[], const c
|
||||
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;
|
||||
@@ -311,8 +461,7 @@ static int parse_iscript_params(char *params, struct polydir_s *poly)
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -394,9 +543,9 @@ static int parse_method(char *method, struct polydir_s *poly,
|
||||
{
|
||||
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 };
|
||||
@@ -421,7 +570,7 @@ static int parse_method(char *method, struct polydir_s *poly,
|
||||
|
||||
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];
|
||||
@@ -467,27 +616,27 @@ static int parse_method(char *method, struct polydir_s *poly,
|
||||
* 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++;
|
||||
|
||||
/*
|
||||
@@ -523,22 +672,19 @@ static int process_line(char *line, const char *home, const char *rhome,
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -553,19 +699,16 @@ static int process_line(char *line, const char *home, const char *rhome,
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
@@ -575,15 +718,8 @@ static int process_line(char *line, const char *home, const char *rhome,
|
||||
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");
|
||||
@@ -594,26 +730,19 @@ static int process_line(char *line, const char *home, const char *rhome,
|
||||
* 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;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -637,7 +766,7 @@ static int process_line(char *line, const char *home, const char *rhome,
|
||||
if (uids) {
|
||||
uid_t *uidptr;
|
||||
const char *ustr, *sstr;
|
||||
- int count, i;
|
||||
+ size_t count, i;
|
||||
|
||||
if (*uids == '~') {
|
||||
poly->flags |= POLYDIR_EXCLUSIVE;
|
||||
@@ -646,8 +775,13 @@ static int process_line(char *line, const char *home, const char *rhome,
|
||||
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;
|
||||
@@ -996,6 +1130,7 @@ static int form_context(const struct polydir_s *polyptr,
|
||||
return rc;
|
||||
}
|
||||
/* Should never get here */
|
||||
+ freecon(scon);
|
||||
return PAM_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
@@ -1057,10 +1192,8 @@ static int poly_name(const struct polydir_s *polyptr, char **i_name,
|
||||
|
||||
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
|
||||
@@ -1070,17 +1203,12 @@ static int poly_name(const struct polydir_s *polyptr, char **i_name,
|
||||
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 */
|
||||
@@ -1110,11 +1238,12 @@ static int poly_name(const struct polydir_s *polyptr, char **i_name,
|
||||
*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;
|
||||
}
|
||||
@@ -1139,137 +1268,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;
|
||||
@@ -1281,13 +1279,12 @@ static int check_inst_parent(char *ipath, struct instance_data *idata)
|
||||
* 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';
|
||||
@@ -1371,9 +1368,10 @@ static int inst_init(const struct polydir_s *polyptr, const char *ipath,
|
||||
if (setuid(geteuid()) < 0) {
|
||||
/* ignore failures, they don't matter */
|
||||
}
|
||||
+ close_fds_pre_exec(idata);
|
||||
|
||||
- if (execle(init_script, init_script,
|
||||
- polyptr->dir, ipath, newdir?"1":"0", idata->user, NULL, envp) < 0)
|
||||
+ 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) &&
|
||||
@@ -1424,7 +1422,9 @@ static int create_polydir(struct polydir_s *polyptr,
|
||||
|
||||
#ifdef WITH_SELINUX
|
||||
if (idata->flags & PAMNS_SELINUX_ENABLED) {
|
||||
- getfscreatecon_raw(&oldcon_raw);
|
||||
+ if (getfscreatecon_raw(&oldcon_raw) != 0)
|
||||
+ pam_syslog(idata->pamh, LOG_NOTICE,
|
||||
+ "Error retrieving fs create context: %m");
|
||||
|
||||
label_handle = selabel_open(SELABEL_CTX_FILE, NULL, 0);
|
||||
if (!label_handle) {
|
||||
@@ -1453,6 +1453,9 @@ static int create_polydir(struct polydir_s *polyptr,
|
||||
if (rc == -1) {
|
||||
pam_syslog(idata->pamh, LOG_ERR,
|
||||
"Error creating directory %s: %m", dir);
|
||||
+#ifdef WITH_SELINUX
|
||||
+ freecon(oldcon_raw);
|
||||
+#endif
|
||||
return PAM_SESSION_ERR;
|
||||
}
|
||||
|
||||
@@ -1640,16 +1643,14 @@ static int ns_setup(struct polydir_s *polyptr,
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -1698,7 +1699,7 @@ static int ns_setup(struct polydir_s *polyptr,
|
||||
#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)
|
||||
@@ -1810,8 +1811,9 @@ static int cleanup_tmpdirs(struct instance_data *idata)
|
||||
_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));
|
||||
@@ -1826,7 +1828,7 @@ static int cleanup_tmpdirs(struct instance_data *idata)
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
diff --git a/modules/pam_namespace/pam_namespace.h b/modules/pam_namespace/pam_namespace.h
|
||||
index a991b4c..180e042 100644
|
||||
--- a/modules/pam_namespace/pam_namespace.h
|
||||
+++ b/modules/pam_namespace/pam_namespace.h
|
||||
@@ -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"
|
||||
@@ -114,7 +109,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 */
|
||||
--
|
||||
2.49.0
|
||||
|
||||
1
sources/poky/meta/recipes-extended/pam/libpam/99_pam
Normal file
1
sources/poky/meta/recipes-extended/pam/libpam/99_pam
Normal file
@@ -0,0 +1 @@
|
||||
d root root 0755 /run/sepermit none
|
||||
@@ -0,0 +1,98 @@
|
||||
From b3020da7da384d769f27a8713257fbe1001878be Mon Sep 17 00:00:00 2001
|
||||
From: "Dmitry V. Levin" <ldv@strace.io>
|
||||
Date: Mon, 1 Jan 2024 12:00:00 +0000
|
||||
Subject: [PATCH] pam_unix/passverify: always run the helper to obtain shadow
|
||||
password file entries
|
||||
|
||||
Initially, when pam_unix.so verified the password, it used to try to
|
||||
obtain the shadow password file entry for the given user by invoking
|
||||
getspnam(3), and only when that didn't work and the effective uid
|
||||
was nonzero, pam_unix.so used to invoke the helper as a fallback.
|
||||
|
||||
When SELinux support was introduced by commit
|
||||
67aab1ff5515054341a438cf9804e9c9b3a88033, the fallback was extended
|
||||
also for the case when SELinux was enabled.
|
||||
|
||||
Later, commit f220cace205332a3dc34e7b37a85e7627e097e7d extended the
|
||||
fallback conditions for the case when pam_modutil_getspnam() failed
|
||||
with EACCES.
|
||||
|
||||
Since commit 470823c4aacef5cb3b1180be6ed70846b61a3752, the helper is
|
||||
invoked as a fallback when pam_modutil_getspnam() fails for any reason.
|
||||
|
||||
The ultimate solution for the case when pam_unix.so does not have
|
||||
permissions to obtain the shadow password file entry is to stop trying
|
||||
to use pam_modutil_getspnam() and to invoke the helper instead.
|
||||
Here are two recent examples.
|
||||
|
||||
https://github.com/linux-pam/linux-pam/pull/484 describes a system
|
||||
configuration where libnss_systemd is enabled along with libnss_files
|
||||
in the shadow entry of nsswitch.conf, so when libnss_files is unable
|
||||
to obtain the shadow password file entry for the root user, e.g. when
|
||||
SELinux is enabled, NSS falls back to libnss_systemd which returns
|
||||
a synthesized shadow password file entry for the root user, which
|
||||
in turn locks the root user out.
|
||||
|
||||
https://bugzilla.redhat.com/show_bug.cgi?id=2150155 describes
|
||||
essentially the same problem in a similar system configuration.
|
||||
|
||||
This commit is the final step in the direction of addressing the issue:
|
||||
for password verification pam_unix.so now invokes the helper instead of
|
||||
making the pam_modutil_getspnam() call.
|
||||
|
||||
* modules/pam_unix/passverify.c (get_account_info) [!HELPER_COMPILE]:
|
||||
Always return PAM_UNIX_RUN_HELPER instead of trying to obtain
|
||||
the shadow password file entry.
|
||||
|
||||
Complements: https://github.com/linux-pam/linux-pam/pull/386
|
||||
Resolves: https://github.com/linux-pam/linux-pam/pull/484
|
||||
Link: https://github.com/authselect/authselect/commit/1e78f7e048747024a846fd22d68afc6993734e92
|
||||
|
||||
CVE: CVE-2024-10041
|
||||
|
||||
Upstream-Status: Backport [https://github.com/linux-pam/linux-pam/commit/b3020da7da384d769f27a8713257fbe1001878be]
|
||||
|
||||
Signed-off-by: Divya Chellam <divya.chellam@windriver.com>
|
||||
---
|
||||
modules/pam_unix/passverify.c | 21 +++++++++++----------
|
||||
1 file changed, 11 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c
|
||||
index 81b10d8..97a81d6 100644
|
||||
--- a/modules/pam_unix/passverify.c
|
||||
+++ b/modules/pam_unix/passverify.c
|
||||
@@ -237,20 +237,21 @@ PAMH_ARG_DECL(int get_account_info,
|
||||
return PAM_UNIX_RUN_HELPER;
|
||||
#endif
|
||||
} else if (is_pwd_shadowed(*pwd)) {
|
||||
+#ifdef HELPER_COMPILE
|
||||
/*
|
||||
- * ...and shadow password file entry for this user,
|
||||
+ * shadow password file entry for this user,
|
||||
* if shadowing is enabled
|
||||
*/
|
||||
- *spwdent = pam_modutil_getspnam(pamh, name);
|
||||
- if (*spwdent == NULL) {
|
||||
-#ifndef HELPER_COMPILE
|
||||
- /* still a chance the user can authenticate */
|
||||
- return PAM_UNIX_RUN_HELPER;
|
||||
-#endif
|
||||
- return PAM_AUTHINFO_UNAVAIL;
|
||||
- }
|
||||
- if ((*spwdent)->sp_pwdp == NULL)
|
||||
+ *spwdent = getspnam(name);
|
||||
+ if (*spwdent == NULL || (*spwdent)->sp_pwdp == NULL)
|
||||
return PAM_AUTHINFO_UNAVAIL;
|
||||
+#else
|
||||
+ /*
|
||||
+ * The helper has to be invoked to deal with
|
||||
+ * the shadow password file entry.
|
||||
+ */
|
||||
+ return PAM_UNIX_RUN_HELPER;
|
||||
+#endif
|
||||
}
|
||||
} else {
|
||||
return PAM_USER_UNKNOWN;
|
||||
--
|
||||
2.40.0
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
From b7b96362087414e52524d3d9d9b3faa21e1db620 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Stoeckmann <tobias@stoeckmann.org>
|
||||
Date: Wed, 24 Jan 2024 18:57:42 +0100
|
||||
Subject: [PATCH] pam_unix: try to set uid to 0 for unix_chkpwd
|
||||
|
||||
The geteuid check does not cover all cases. If a program runs with
|
||||
elevated capabilities like CAP_SETUID then we can still check
|
||||
credentials of other users.
|
||||
|
||||
Keep logging for future analysis though.
|
||||
|
||||
Resolves: https://github.com/linux-pam/linux-pam/issues/747
|
||||
Fixes: b3020da7da38 ("pam_unix/passverify: always run the helper to obtain shadow password file entries")
|
||||
|
||||
Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
|
||||
|
||||
Upstream-Status: Backport [https://github.com/linux-pam/linux-pam/commit/b7b96362087414e52524d3d9d9b3faa21e1db620]
|
||||
CVE: CVE-2024-10041
|
||||
Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
|
||||
---
|
||||
modules/pam_unix/pam_unix_acct.c | 17 +++++++++--------
|
||||
modules/pam_unix/support.c | 14 +++++++-------
|
||||
2 files changed, 16 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/modules/pam_unix/pam_unix_acct.c b/modules/pam_unix/pam_unix_acct.c
|
||||
index 8f5ed3e0df..7ffcb9e3f2 100644
|
||||
--- a/modules/pam_unix/pam_unix_acct.c
|
||||
+++ b/modules/pam_unix/pam_unix_acct.c
|
||||
@@ -110,14 +110,15 @@ int _unix_run_verify_binary(pam_handle_t *pamh, unsigned long long ctrl,
|
||||
_exit(PAM_AUTHINFO_UNAVAIL);
|
||||
}
|
||||
|
||||
- if (geteuid() == 0) {
|
||||
- /* must set the real uid to 0 so the helper will not error
|
||||
- out if pam is called from setuid binary (su, sudo...) */
|
||||
- if (setuid(0) == -1) {
|
||||
- pam_syslog(pamh, LOG_ERR, "setuid failed: %m");
|
||||
- printf("-1\n");
|
||||
- fflush(stdout);
|
||||
- _exit(PAM_AUTHINFO_UNAVAIL);
|
||||
+ /* must set the real uid to 0 so the helper will not error
|
||||
+ out if pam is called from setuid binary (su, sudo...) */
|
||||
+ if (setuid(0) == -1) {
|
||||
+ uid_t euid = geteuid();
|
||||
+ pam_syslog(pamh, euid == 0 ? LOG_ERR : LOG_DEBUG, "setuid failed: %m");
|
||||
+ if (euid == 0) {
|
||||
+ printf("-1\n");
|
||||
+ fflush(stdout);
|
||||
+ _exit(PAM_AUTHINFO_UNAVAIL);
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/modules/pam_unix/support.c b/modules/pam_unix/support.c
|
||||
index d391973f95..69811048e6 100644
|
||||
--- a/modules/pam_unix/support.c
|
||||
+++ b/modules/pam_unix/support.c
|
||||
@@ -562,13 +562,13 @@ static int _unix_run_helper_binary(pam_handle_t *pamh, const char *passwd,
|
||||
_exit(PAM_AUTHINFO_UNAVAIL);
|
||||
}
|
||||
|
||||
- if (geteuid() == 0) {
|
||||
- /* must set the real uid to 0 so the helper will not error
|
||||
- out if pam is called from setuid binary (su, sudo...) */
|
||||
- if (setuid(0) == -1) {
|
||||
- D(("setuid failed"));
|
||||
- _exit(PAM_AUTHINFO_UNAVAIL);
|
||||
- }
|
||||
+ /* must set the real uid to 0 so the helper will not error
|
||||
+ out if pam is called from setuid binary (su, sudo...) */
|
||||
+ if (setuid(0) == -1) {
|
||||
+ D(("setuid failed"));
|
||||
+ if (geteuid() == 0) {
|
||||
+ _exit(PAM_AUTHINFO_UNAVAIL);
|
||||
+ }
|
||||
}
|
||||
|
||||
/* exec binary helper */
|
||||
@@ -0,0 +1,65 @@
|
||||
From 84f378d3b8573828e7ccc54b54b5e128aa993748 Mon Sep 17 00:00:00 2001
|
||||
From: Matthias Gerstner <matthias.gerstner@suse.de>
|
||||
Date: Wed, 27 Dec 2023 14:01:59 +0100
|
||||
Subject: [PATCH] pam_namespace: protect_dir(): use O_DIRECTORY to prevent
|
||||
local DoS situations
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Without O_DIRECTORY the path crawling logic is subject to e.g. FIFOs
|
||||
being placed in user controlled directories, causing the PAM module to
|
||||
block indefinitely during `openat()`.
|
||||
|
||||
Pass O_DIRECTORY to cause the `openat()` to fail if the path does not
|
||||
refer to a directory.
|
||||
|
||||
With this the check whether the final path element is a directory
|
||||
becomes unnecessary, drop it.
|
||||
|
||||
Upstream-Status: Backport [https://github.com/linux-pam/linux-pam/commit/031bb5a5d0d950253b68138b498dc93be69a64cb]
|
||||
CVE: CVE-2024-22365
|
||||
Signed-off-by: Guðni Már Gilbert <gudni.m.g@gmail.com>
|
||||
---
|
||||
modules/pam_namespace/pam_namespace.c | 18 +-----------------
|
||||
1 file changed, 1 insertion(+), 17 deletions(-)
|
||||
|
||||
diff --git a/modules/pam_namespace/pam_namespace.c b/modules/pam_namespace/pam_namespace.c
|
||||
index f34ce934..ef856443 100644
|
||||
--- a/modules/pam_namespace/pam_namespace.c
|
||||
+++ b/modules/pam_namespace/pam_namespace.c
|
||||
@@ -1194,7 +1194,7 @@ static int protect_dir(const char *path, mode_t mode, int do_mkdir,
|
||||
int dfd = AT_FDCWD;
|
||||
int dfd_next;
|
||||
int save_errno;
|
||||
- int flags = O_RDONLY;
|
||||
+ int flags = O_RDONLY | O_DIRECTORY;
|
||||
int rv = -1;
|
||||
struct stat st;
|
||||
|
||||
@@ -1248,22 +1248,6 @@ static int protect_dir(const char *path, mode_t mode, int do_mkdir,
|
||||
rv = openat(dfd, dir, flags);
|
||||
}
|
||||
|
||||
- if (rv != -1) {
|
||||
- if (fstat(rv, &st) != 0) {
|
||||
- save_errno = errno;
|
||||
- close(rv);
|
||||
- rv = -1;
|
||||
- errno = save_errno;
|
||||
- goto error;
|
||||
- }
|
||||
- if (!S_ISDIR(st.st_mode)) {
|
||||
- close(rv);
|
||||
- errno = ENOTDIR;
|
||||
- rv = -1;
|
||||
- goto error;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
if (flags & O_NOFOLLOW) {
|
||||
/* we are inside user-owned dir - protect */
|
||||
if (protect_mount(rv, p, idata) == -1) {
|
||||
--
|
||||
2.43.0
|
||||
|
||||
1128
sources/poky/meta/recipes-extended/pam/libpam/CVE-2025-6020-01.patch
Normal file
1128
sources/poky/meta/recipes-extended/pam/libpam/CVE-2025-6020-01.patch
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,187 @@
|
||||
From 592d84e1265d04c3104acee815a503856db503a1 Mon Sep 17 00:00:00 2001
|
||||
From: Olivier Bal-Petre <olivier.bal-petre@ssi.gouv.fr>
|
||||
Date: Tue, 4 Mar 2025 14:37:02 +0100
|
||||
Subject: [PATCH] pam_namespace: add flags to indicate path safety
|
||||
|
||||
Add two flags in the script to indicate if the paths to the polydir
|
||||
and the instance directories are safe (root owned and writable by
|
||||
root only).
|
||||
|
||||
Signed-off-by: Olivier Bal-Petre <olivier.bal-petre@ssi.gouv.fr>
|
||||
Signed-off-by: Dmitry V. Levin <ldv@strace.io>
|
||||
|
||||
Upstream-Status: Backport [https://github.com/linux-pam/linux-pam/commit/592d84e1265d04c3104acee815a503856db503a1]
|
||||
CVE: CVE-2025-6020
|
||||
Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
|
||||
---
|
||||
modules/pam_namespace/namespace.init | 56 ++++++++++++-------
|
||||
modules/pam_namespace/pam_namespace.c | 79 ++++++++++++++++++++++++++-
|
||||
2 files changed, 115 insertions(+), 20 deletions(-)
|
||||
|
||||
diff --git a/modules/pam_namespace/namespace.init b/modules/pam_namespace/namespace.init
|
||||
index d9053a1..8782178 100755
|
||||
--- a/modules/pam_namespace/namespace.init
|
||||
+++ b/modules/pam_namespace/namespace.init
|
||||
@@ -1,25 +1,43 @@
|
||||
#!/bin/sh
|
||||
-# It receives polydir path as $1, the instance path as $2,
|
||||
-# a flag whether the instance dir was newly created (0 - no, 1 - yes) in $3,
|
||||
-# and user name in $4.
|
||||
+# It receives as arguments:
|
||||
+# - $1 polydir path (see WARNING below)
|
||||
+# - $2 instance path (see WARNING below)
|
||||
+# - $3 flag whether the instance dir was newly created (0 - no, 1 - yes)
|
||||
+# - $4 user name
|
||||
+# - $5 flag whether the polydir path ($1) is safe (0 - unsafe, 1 -safe)
|
||||
+# - $6 flag whether the instance path ($2) is safe (0 - unsafe, 1 - safe)
|
||||
+#
|
||||
+# WARNING: This script is invoked with full root privileges. Accessing
|
||||
+# the polydir ($1) and the instance ($2) directories in this context may be
|
||||
+# extremely dangerous as those can be under user control. The flags $5 and $6
|
||||
+# are provided to let you know if all the segments part of the path (except the
|
||||
+# last one) are owned by root and are writable by root only. If the path does
|
||||
+# not meet these criteria, you expose yourself to possible symlink attacks when
|
||||
+# accessing these path.
|
||||
+# However, even if the path components are safe, the content of the
|
||||
+# directories may still be owned/writable by a user, so care must be taken!
|
||||
#
|
||||
# The following section will copy the contents of /etc/skel if this is a
|
||||
# newly created home directory.
|
||||
-if [ "$3" = 1 ]; then
|
||||
- # This line will fix the labeling on all newly created directories
|
||||
- [ -x /sbin/restorecon ] && /sbin/restorecon "$1"
|
||||
- user="$4"
|
||||
- passwd=$(getent passwd "$user")
|
||||
- homedir=$(echo "$passwd" | cut -f6 -d":")
|
||||
- if [ "$1" = "$homedir" ]; 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)))
|
||||
- chmod ${mode:-700} "$homedir"
|
||||
- [ -x /sbin/restorecon ] && /sbin/restorecon -R "$homedir"
|
||||
- fi
|
||||
-fi
|
||||
|
||||
+# Executes only if the polydir path is safe
|
||||
+if [ "$5" = 1 ]; then
|
||||
+
|
||||
+ if [ "$3" = 1 ]; then
|
||||
+ # This line will fix the labeling on all newly created directories
|
||||
+ [ -x /sbin/restorecon ] && /sbin/restorecon "$1"
|
||||
+ user="$4"
|
||||
+ passwd=$(getent passwd "$user")
|
||||
+ homedir=$(echo "$passwd" | cut -f6 -d":")
|
||||
+ if [ "$1" = "$homedir" ]; then
|
||||
+ gid=$(echo "$passwd" | cut -f4 -d":")
|
||||
+ cp -rT /etc/skel "$homedir"
|
||||
+ chown -R "$user":"$gid" "$homedir"
|
||||
+ 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
|
||||
+ fi
|
||||
+fi
|
||||
exit 0
|
||||
diff --git a/modules/pam_namespace/pam_namespace.c b/modules/pam_namespace/pam_namespace.c
|
||||
index 9d993d4..4c8153b 100644
|
||||
--- a/modules/pam_namespace/pam_namespace.c
|
||||
+++ b/modules/pam_namespace/pam_namespace.c
|
||||
@@ -1467,6 +1467,79 @@ static int check_inst_parent(int dfd, struct instance_data *idata)
|
||||
return PAM_SUCCESS;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Check for a given absolute path that all segments except the last one are:
|
||||
+ * 1. a directory owned by root and not writable by group or others
|
||||
+ * 2. a symlink owned by root and referencing a directory respecting 1.
|
||||
+ * Returns 0 if safe, -1 is unsafe.
|
||||
+ * If the path is not accessible (does not exist, hidden under a mount...),
|
||||
+ * returns -1 (unsafe).
|
||||
+ */
|
||||
+static int check_safe_path(const char *path, struct instance_data *idata)
|
||||
+{
|
||||
+ char *p = strdup(path);
|
||||
+ char *d;
|
||||
+ char *dir = p;
|
||||
+ struct stat st;
|
||||
+
|
||||
+ if (p == NULL)
|
||||
+ return -1;
|
||||
+
|
||||
+ /* Check path is absolute */
|
||||
+ if (p[0] != '/')
|
||||
+ goto error;
|
||||
+
|
||||
+ strip_trailing_slashes(p);
|
||||
+
|
||||
+ /* Last segment of the path may be owned by the user */
|
||||
+ if ((d = strrchr(dir, '/')) != NULL)
|
||||
+ *d = '\0';
|
||||
+
|
||||
+ while ((d=strrchr(dir, '/')) != NULL) {
|
||||
+
|
||||
+ /* Do not follow symlinks */
|
||||
+ if (lstat(dir, &st) != 0)
|
||||
+ goto error;
|
||||
+
|
||||
+ if (S_ISLNK(st.st_mode)) {
|
||||
+ if (st.st_uid != 0) {
|
||||
+ if (idata->flags & PAMNS_DEBUG)
|
||||
+ pam_syslog(idata->pamh, LOG_DEBUG,
|
||||
+ "Path deemed unsafe: Symlink %s should be owned by root", dir);
|
||||
+ goto error;
|
||||
+ }
|
||||
+
|
||||
+ /* Follow symlinks */
|
||||
+ if (stat(dir, &st) != 0)
|
||||
+ goto error;
|
||||
+ }
|
||||
+
|
||||
+ if (!S_ISDIR(st.st_mode)) {
|
||||
+ if (idata->flags & PAMNS_DEBUG)
|
||||
+ pam_syslog(idata->pamh, LOG_DEBUG,
|
||||
+ "Path deemed unsafe: %s is expected to be a directory", dir);
|
||||
+ goto error;
|
||||
+ }
|
||||
+
|
||||
+ if (st.st_uid != 0 ||
|
||||
+ ((st.st_mode & (S_IWGRP|S_IWOTH)) && !(st.st_mode & S_ISVTX))) {
|
||||
+ if (idata->flags & PAMNS_DEBUG)
|
||||
+ pam_syslog(idata->pamh, LOG_DEBUG,
|
||||
+ "Path deemed unsafe: %s should be owned by root, and not be writable by group or others", dir);
|
||||
+ goto error;
|
||||
+ }
|
||||
+
|
||||
+ *d = '\0';
|
||||
+ }
|
||||
+
|
||||
+ free(p);
|
||||
+ return 0;
|
||||
+
|
||||
+error:
|
||||
+ free(p);
|
||||
+ return -1;
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Check to see if there is a namespace initialization script in
|
||||
* the /etc/security directory. If such a script exists
|
||||
@@ -1524,7 +1597,11 @@ static int inst_init(const struct polydir_s *polyptr, const char *ipath,
|
||||
close_fds_pre_exec(idata);
|
||||
|
||||
execle(init_script, init_script,
|
||||
- polyptr->dir, ipath, newdir?"1":"0", idata->user, NULL, envp);
|
||||
+ polyptr->dir, ipath,
|
||||
+ newdir ? "1":"0", idata->user,
|
||||
+ (check_safe_path(polyptr->dir, idata) == -1) ? "0":"1",
|
||||
+ (check_safe_path(ipath, idata) == -1) ? "0":"1",
|
||||
+ NULL, envp);
|
||||
_exit(1);
|
||||
} else if (pid > 0) {
|
||||
while (((rc = waitpid(pid, &status, 0)) == (pid_t)-1) &&
|
||||
--
|
||||
2.49.0
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
From 976c20079358d133514568fc7fd95c02df8b5773 Mon Sep 17 00:00:00 2001
|
||||
From: "Dmitry V. Levin" <ldv@strace.io>
|
||||
Date: Tue, 27 May 2025 08:00:00 +0000
|
||||
Subject: [PATCH] pam_namespace: secure_opendir: do not look at the group
|
||||
ownership
|
||||
|
||||
When the directory is not group-writable, the group ownership does
|
||||
not matter, and when it is group-writable, there should not be any
|
||||
exceptions for the root group as there is no guarantee that the root
|
||||
group does not include non-root users.
|
||||
|
||||
Upstream-Status: Backport [https://github.com/linux-pam/linux-pam/commit/976c20079358d133514568fc7fd95c02df8b5773]
|
||||
CVE: CVE-2025-6020
|
||||
Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
|
||||
---
|
||||
modules/pam_namespace/pam_namespace.c | 3 +--
|
||||
1 file changed, 1 insertion(+), 2 deletions(-)
|
||||
|
||||
diff --git a/modules/pam_namespace/pam_namespace.c b/modules/pam_namespace/pam_namespace.c
|
||||
index 4c8153b..791dd07 100644
|
||||
--- a/modules/pam_namespace/pam_namespace.c
|
||||
+++ b/modules/pam_namespace/pam_namespace.c
|
||||
@@ -215,8 +215,7 @@ static int secure_opendir(const char *path, int opm, mode_t mode,
|
||||
if (dfd_next == -1)
|
||||
goto error;
|
||||
} else if (st.st_uid != 0
|
||||
- || (st.st_gid != 0 && (st.st_mode & S_IWGRP))
|
||||
- || (st.st_mode & S_IWOTH)) {
|
||||
+ || (st.st_mode & (S_IWGRP|S_IWOTH))) {
|
||||
/* do not follow symlinks on subdirectories */
|
||||
flags |= O_NOFOLLOW;
|
||||
}
|
||||
--
|
||||
2.49.0
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
This patch is used to create a new sub package libpam-xtests to do more checks.
|
||||
|
||||
Upstream-Status: Pending
|
||||
|
||||
Signed-off-by: Kang Kai <kai.kang@windriver.com>
|
||||
Index: Linux-PAM-1.3.0/xtests/Makefile.am
|
||||
===================================================================
|
||||
--- Linux-PAM-1.3.0.orig/xtests/Makefile.am
|
||||
+++ Linux-PAM-1.3.0/xtests/Makefile.am
|
||||
@@ -7,7 +7,7 @@ AM_CFLAGS = -DLIBPAM_COMPILE -I$(top_src
|
||||
LDADD = $(top_builddir)/libpam/libpam.la \
|
||||
$(top_builddir)/libpam_misc/libpam_misc.la
|
||||
|
||||
-CLEANFILES = *~ $(XTESTS)
|
||||
+CLEANFILES = *~
|
||||
|
||||
EXTRA_DIST = run-xtests.sh tst-pam_dispatch1.pamd tst-pam_dispatch2.pamd \
|
||||
tst-pam_dispatch3.pamd tst-pam_dispatch4.pamd \
|
||||
@@ -51,3 +51,18 @@ EXTRA_PROGRAMS = $(XTESTS)
|
||||
|
||||
xtests: $(XTESTS) run-xtests.sh
|
||||
"$(srcdir)"/run-xtests.sh "$(srcdir)" ${XTESTS} ${NOSRCTESTS}
|
||||
+
|
||||
+all: $(XTESTS)
|
||||
+
|
||||
+install: install_xtests
|
||||
+
|
||||
+install_xtests:
|
||||
+ $(INSTALL) -d $(DESTDIR)$(pkgdatadir)/xtests
|
||||
+ for file in $(EXTRA_DIST) ; do \
|
||||
+ $(INSTALL) $(srcdir)/$$file $(DESTDIR)$(pkgdatadir)/xtests ; \
|
||||
+ done
|
||||
+ for file in $(XTESTS); do \
|
||||
+ $(INSTALL) .libs/$$file $(DESTDIR)$(pkgdatadir)/xtests ; \
|
||||
+ done
|
||||
+
|
||||
+.PHONY: all install_xtests
|
||||
@@ -0,0 +1 @@
|
||||
d /run/sepermit 0755 root root - -
|
||||
@@ -0,0 +1,25 @@
|
||||
#
|
||||
# /etc/pam.d/common-account - authorization settings common to all services
|
||||
#
|
||||
# This file is included from other service-specific PAM config files,
|
||||
# and should contain a list of the authorization modules that define
|
||||
# the central access policy for use on the system. The default is to
|
||||
# only deny service to users whose accounts are expired in /etc/shadow.
|
||||
#
|
||||
# As of pam 1.0.1-6, this file is managed by pam-auth-update by default.
|
||||
# To take advantage of this, it is recommended that you configure any
|
||||
# local modules either before or after the default block, and use
|
||||
# pam-auth-update to manage selection of other modules. See
|
||||
# pam-auth-update(8) for details.
|
||||
#
|
||||
|
||||
# here are the per-package modules (the "Primary" block)
|
||||
account [success=1 new_authtok_reqd=done default=ignore] pam_unix.so
|
||||
# here's the fallback if no module succeeds
|
||||
account requisite pam_deny.so
|
||||
# prime the stack with a positive return value if there isn't one already;
|
||||
# this avoids us returning an error just because nothing sets a success code
|
||||
# since the modules above will each just jump around
|
||||
account required pam_permit.so
|
||||
# and here are more per-package modules (the "Additional" block)
|
||||
# end of pam-auth-update config
|
||||
@@ -0,0 +1,18 @@
|
||||
#
|
||||
# /etc/pam.d/common-auth - authentication settings common to all services
|
||||
#
|
||||
# This file is included from other service-specific PAM config files,
|
||||
# and should contain a list of the authentication modules that define
|
||||
# the central authentication scheme for use on the system
|
||||
# (e.g., /etc/shadow, LDAP, Kerberos, etc.). The default is to use the
|
||||
# traditional Unix authentication mechanisms.
|
||||
|
||||
# here are the per-package modules (the "Primary" block)
|
||||
auth [success=1 default=ignore] pam_unix.so nullok_secure
|
||||
# here's the fallback if no module succeeds
|
||||
auth requisite pam_deny.so
|
||||
# prime the stack with a positive return value if there isn't one already;
|
||||
# this avoids us returning an error just because nothing sets a success code
|
||||
# since the modules above will each just jump around
|
||||
auth required pam_permit.so
|
||||
# and here are more per-package modules (the "Additional" block)
|
||||
@@ -0,0 +1,23 @@
|
||||
#
|
||||
# /etc/pam.d/common-password - password-related modules common to all services
|
||||
#
|
||||
# This file is included from other service-specific PAM config files,
|
||||
# and should contain a list of modules that define the services to be
|
||||
# used to change user passwords. The default is pam_unix.
|
||||
|
||||
# Explanation of pam_unix options:
|
||||
#
|
||||
# The "sha512" option enables salted SHA512 passwords. Without this option,
|
||||
# the default is Unix crypt. Prior releases used the option "md5".
|
||||
#
|
||||
# See the pam_unix manpage for other options.
|
||||
|
||||
# here are the per-package modules (the "Primary" block)
|
||||
password [success=1 default=ignore] pam_unix.so sha512
|
||||
# here's the fallback if no module succeeds
|
||||
password requisite pam_deny.so
|
||||
# prime the stack with a positive return value if there isn't one already;
|
||||
# this avoids us returning an error just because nothing sets a success code
|
||||
# since the modules above will each just jump around
|
||||
password required pam_permit.so
|
||||
# and here are more per-package modules (the "Additional" block)
|
||||
@@ -0,0 +1,19 @@
|
||||
#
|
||||
# /etc/pam.d/common-session - session-related modules common to all services
|
||||
#
|
||||
# This file is included from other service-specific PAM config files,
|
||||
# and should contain a list of modules that define tasks to be performed
|
||||
# at the start and end of sessions of *any* kind (both interactive and
|
||||
# non-interactive).
|
||||
#
|
||||
|
||||
# here are the per-package modules (the "Primary" block)
|
||||
session [default=1] pam_permit.so
|
||||
# here's the fallback if no module succeeds
|
||||
session requisite pam_deny.so
|
||||
# prime the stack with a positive return value if there isn't one already;
|
||||
# this avoids us returning an error just because nothing sets a success code
|
||||
# since the modules above will each just jump around
|
||||
session required pam_permit.so
|
||||
# and here are more per-package modules (the "Additional" block)
|
||||
session required pam_unix.so
|
||||
@@ -0,0 +1,19 @@
|
||||
#
|
||||
# /etc/pam.d/common-session-noninteractive - session-related modules
|
||||
# common to all non-interactive services
|
||||
#
|
||||
# This file is included from other service-specific PAM config files,
|
||||
# and should contain a list of modules that define tasks to be performed
|
||||
# at the start and end of all non-interactive sessions.
|
||||
#
|
||||
|
||||
# here are the per-package modules (the "Primary" block)
|
||||
session [default=1] pam_permit.so
|
||||
# here's the fallback if no module succeeds
|
||||
session requisite pam_deny.so
|
||||
# prime the stack with a positive return value if there isn't one already;
|
||||
# this avoids us returning an error just because nothing sets a success code
|
||||
# since the modules above will each just jump around
|
||||
session required pam_permit.so
|
||||
# and here are more per-package modules (the "Additional" block)
|
||||
session required pam_unix.so
|
||||
24
sources/poky/meta/recipes-extended/pam/libpam/pam.d/other
Normal file
24
sources/poky/meta/recipes-extended/pam/libpam/pam.d/other
Normal file
@@ -0,0 +1,24 @@
|
||||
#
|
||||
# /etc/pam.d/other - specify the PAM fallback behaviour
|
||||
#
|
||||
# Note that this file is used for any unspecified service; for example
|
||||
#if /etc/pam.d/cron specifies no session modules but cron calls
|
||||
#pam_open_session, the session module out of /etc/pam.d/other is
|
||||
#used.
|
||||
|
||||
# We use pam_warn.so to generate syslog notes that the 'other'
|
||||
#fallback rules are being used (as a hint to suggest you should setup
|
||||
#specific PAM rules for the service and aid to debugging). Then to be
|
||||
#secure, deny access to all services by default.
|
||||
|
||||
auth required pam_warn.so
|
||||
auth required pam_deny.so
|
||||
|
||||
account required pam_warn.so
|
||||
account required pam_deny.so
|
||||
|
||||
password required pam_warn.so
|
||||
password required pam_deny.so
|
||||
|
||||
session required pam_warn.so
|
||||
session required pam_deny.so
|
||||
32
sources/poky/meta/recipes-extended/pam/libpam/run-ptest
Normal file
32
sources/poky/meta/recipes-extended/pam/libpam/run-ptest
Normal file
@@ -0,0 +1,32 @@
|
||||
#! /bin/sh
|
||||
|
||||
cd tests
|
||||
|
||||
export srcdir=.
|
||||
|
||||
failed=0
|
||||
all=0
|
||||
for f in tst-*; do
|
||||
"./$f" > /dev/null 2>&1
|
||||
case "$?" in
|
||||
0)
|
||||
echo "PASS: $f"
|
||||
all=$((all + 1))
|
||||
;;
|
||||
77)
|
||||
echo "SKIP: $f"
|
||||
;;
|
||||
*)
|
||||
echo "FAIL: $f"
|
||||
failed=$((failed + 1))
|
||||
all=$((all + 1))
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ "$failed" -eq 0 ] ; then
|
||||
echo "All $all tests passed"
|
||||
else
|
||||
echo "$failed of $all tests failed"
|
||||
fi
|
||||
unset srcdir
|
||||
201
sources/poky/meta/recipes-extended/pam/libpam_1.5.3.bb
Normal file
201
sources/poky/meta/recipes-extended/pam/libpam_1.5.3.bb
Normal file
@@ -0,0 +1,201 @@
|
||||
DISABLE_STATIC = ""
|
||||
SUMMARY = "Linux-PAM (Pluggable Authentication Modules)"
|
||||
DESCRIPTION = "Linux-PAM (Pluggable Authentication Modules for Linux), a flexible mechanism for authenticating users"
|
||||
HOMEPAGE = "https://fedorahosted.org/linux-pam/"
|
||||
BUGTRACKER = "https://fedorahosted.org/linux-pam/newticket"
|
||||
SECTION = "base"
|
||||
# PAM is dual licensed under GPL and BSD.
|
||||
# /etc/pam.d comes from Debian libpam-runtime in 2009-11 (at that time
|
||||
# libpam-runtime-1.0.1 is GPL-2.0-or-later), by openembedded
|
||||
LICENSE = "GPL-2.0-or-later | BSD-3-Clause"
|
||||
LIC_FILES_CHKSUM = "file://COPYING;md5=7eb5c1bf854e8881005d673599ee74d3 \
|
||||
file://libpamc/License;md5=a4da476a14c093fdc73be3c3c9ba8fb3 \
|
||||
"
|
||||
|
||||
SRC_URI = "${GITHUB_BASE_URI}/download/v${PV}/Linux-PAM-${PV}.tar.xz \
|
||||
file://99_pam \
|
||||
file://pam.d/common-account \
|
||||
file://pam.d/common-auth \
|
||||
file://pam.d/common-password \
|
||||
file://pam.d/common-session \
|
||||
file://pam.d/common-session-noninteractive \
|
||||
file://pam.d/other \
|
||||
file://libpam-xtests.patch \
|
||||
file://0001-examples-Replace-use-of-termio.h-with-termios.h.patch \
|
||||
file://run-ptest \
|
||||
file://pam-volatiles.conf \
|
||||
file://0001-pam_namespace-include-stdint-h.patch \
|
||||
file://0001-pam_pwhistory-fix-passing-NULL-filename-argument-to-.patch \
|
||||
file://CVE-2024-22365.patch \
|
||||
file://CVE-2024-10041-1.patch \
|
||||
file://CVE-2024-10041-2.patch \
|
||||
file://0001-pam-inline-pam-asprintf.patch \
|
||||
file://0002-pam-namespace-rebase.patch \
|
||||
file://CVE-2025-6020-01.patch \
|
||||
file://CVE-2025-6020-02.patch \
|
||||
file://CVE-2025-6020-03.patch \
|
||||
"
|
||||
|
||||
SRC_URI[sha256sum] = "7ac4b50feee004a9fa88f1dfd2d2fa738a82896763050cd773b3c54b0a818283"
|
||||
|
||||
DEPENDS = "bison-native flex-native libxml2-native virtual/crypt"
|
||||
|
||||
EXTRA_OECONF = "--includedir=${includedir}/security \
|
||||
--libdir=${base_libdir} \
|
||||
--with-systemdunitdir=${systemd_system_unitdir} \
|
||||
--disable-nis \
|
||||
--disable-regenerate-docu \
|
||||
--disable-doc \
|
||||
--disable-prelude"
|
||||
|
||||
CFLAGS:append = " -fPIC "
|
||||
|
||||
S = "${WORKDIR}/Linux-PAM-${PV}"
|
||||
|
||||
inherit autotools gettext pkgconfig systemd ptest github-releases
|
||||
|
||||
PACKAGECONFIG ??= ""
|
||||
PACKAGECONFIG[audit] = "--enable-audit,--disable-audit,audit,"
|
||||
PACKAGECONFIG[userdb] = "--enable-db=db,--enable-db=no,db,"
|
||||
|
||||
PACKAGES += "${PN}-runtime ${PN}-xtests"
|
||||
FILES:${PN} = " \
|
||||
${base_libdir}/lib*${SOLIBS} \
|
||||
${nonarch_libdir}/tmpfiles.d/*.conf \
|
||||
"
|
||||
FILES:${PN}-dev += "${base_libdir}/security/*.la ${base_libdir}/*.la ${base_libdir}/lib*${SOLIBSDEV}"
|
||||
FILES:${PN}-runtime = "${sysconfdir} ${sbindir} ${systemd_system_unitdir}"
|
||||
FILES:${PN}-xtests = "${datadir}/Linux-PAM/xtests"
|
||||
|
||||
# libpam installs /etc/environment for use with the pam_env plugin. Make sure it is
|
||||
# packaged with the pam-plugin-env package to avoid breaking installations which
|
||||
# install that file via other packages
|
||||
FILES:pam-plugin-env = "${sysconfdir}/environment"
|
||||
|
||||
PACKAGES_DYNAMIC += "^${MLPREFIX}pam-plugin-.*"
|
||||
|
||||
def get_multilib_bit(d):
|
||||
baselib = d.getVar('baselib') or ''
|
||||
return baselib.replace('lib', '')
|
||||
|
||||
libpam_suffix = "suffix${@get_multilib_bit(d)}"
|
||||
|
||||
RPROVIDES:${PN} += "${PN}-${libpam_suffix}"
|
||||
RPROVIDES:${PN}-runtime += "${PN}-runtime-${libpam_suffix}"
|
||||
|
||||
RDEPENDS:${PN}-runtime = "${PN}-${libpam_suffix} \
|
||||
${MLPREFIX}pam-plugin-deny-${libpam_suffix} \
|
||||
${MLPREFIX}pam-plugin-permit-${libpam_suffix} \
|
||||
${MLPREFIX}pam-plugin-warn-${libpam_suffix} \
|
||||
${MLPREFIX}pam-plugin-unix-${libpam_suffix} \
|
||||
"
|
||||
RDEPENDS:${PN}-xtests = "${PN}-${libpam_suffix} \
|
||||
${MLPREFIX}pam-plugin-access-${libpam_suffix} \
|
||||
${MLPREFIX}pam-plugin-debug-${libpam_suffix} \
|
||||
${MLPREFIX}pam-plugin-pwhistory-${libpam_suffix} \
|
||||
${MLPREFIX}pam-plugin-succeed-if-${libpam_suffix} \
|
||||
${MLPREFIX}pam-plugin-time-${libpam_suffix} \
|
||||
bash coreutils"
|
||||
|
||||
# FIXME: Native suffix breaks here, disable it for now
|
||||
RRECOMMENDS:${PN} = "${PN}-runtime-${libpam_suffix}"
|
||||
RRECOMMENDS:${PN}:class-native = ""
|
||||
|
||||
python populate_packages:prepend () {
|
||||
def pam_plugin_hook(file, pkg, pattern, format, basename):
|
||||
pn = d.getVar('PN')
|
||||
libpam_suffix = d.getVar('libpam_suffix')
|
||||
|
||||
rdeps = d.getVar('RDEPENDS:' + pkg)
|
||||
if rdeps:
|
||||
rdeps = rdeps + " " + pn + "-" + libpam_suffix
|
||||
else:
|
||||
rdeps = pn + "-" + libpam_suffix
|
||||
d.setVar('RDEPENDS:' + pkg, rdeps)
|
||||
|
||||
provides = d.getVar('RPROVIDES:' + pkg)
|
||||
if provides:
|
||||
provides = provides + " " + pkg + "-" + libpam_suffix
|
||||
else:
|
||||
provides = pkg + "-" + libpam_suffix
|
||||
d.setVar('RPROVIDES:' + pkg, provides)
|
||||
|
||||
mlprefix = d.getVar('MLPREFIX') or ''
|
||||
dvar = d.expand('${WORKDIR}/package')
|
||||
pam_libdir = d.expand('${base_libdir}/security')
|
||||
pam_sbindir = d.expand('${sbindir}')
|
||||
pam_filterdir = d.expand('${base_libdir}/security/pam_filter')
|
||||
pam_pkgname = mlprefix + 'pam-plugin%s'
|
||||
|
||||
do_split_packages(d, pam_libdir, r'^pam(.*)\.so$', pam_pkgname,
|
||||
'PAM plugin for %s', hook=pam_plugin_hook, extra_depends='', prepend=True)
|
||||
do_split_packages(d, pam_filterdir, r'^(.*)$', 'pam-filter-%s', 'PAM filter for %s', extra_depends='')
|
||||
}
|
||||
|
||||
do_compile_ptest() {
|
||||
cd tests
|
||||
sed -i -e 's/$(MAKE) $(AM_MAKEFLAGS) check-TESTS//' Makefile
|
||||
oe_runmake check-am
|
||||
cd -
|
||||
}
|
||||
|
||||
do_install() {
|
||||
autotools_do_install
|
||||
|
||||
# don't install /var/run when populating rootfs. Do it through volatile
|
||||
rm -rf ${D}${localstatedir}
|
||||
|
||||
if ${@bb.utils.contains('DISTRO_FEATURES','sysvinit','false','true',d)}; then
|
||||
rm -rf ${D}${sysconfdir}/init.d/
|
||||
rm -rf ${D}${sysconfdir}/rc*
|
||||
install -d ${D}${nonarch_libdir}/tmpfiles.d
|
||||
install -m 0644 ${WORKDIR}/pam-volatiles.conf \
|
||||
${D}${nonarch_libdir}/tmpfiles.d/pam.conf
|
||||
else
|
||||
install -d ${D}${sysconfdir}/default/volatiles
|
||||
install -m 0644 ${WORKDIR}/99_pam \
|
||||
${D}${sysconfdir}/default/volatiles/
|
||||
fi
|
||||
|
||||
install -d ${D}${sysconfdir}/pam.d/
|
||||
install -m 0644 ${WORKDIR}/pam.d/* ${D}${sysconfdir}/pam.d/
|
||||
|
||||
# The lsb requires unix_chkpwd has setuid permission
|
||||
chmod 4755 ${D}${sbindir}/unix_chkpwd
|
||||
|
||||
if ${@bb.utils.contains('DISTRO_FEATURES','systemd','true','false',d)}; then
|
||||
echo "session optional pam_systemd.so" >> ${D}${sysconfdir}/pam.d/common-session
|
||||
fi
|
||||
if ${@bb.utils.contains('DISTRO_FEATURES','usrmerge','false','true',d)}; then
|
||||
install -d ${D}/${libdir}/
|
||||
mv ${D}/${base_libdir}/pkgconfig ${D}/${libdir}/
|
||||
fi
|
||||
}
|
||||
|
||||
do_install_ptest() {
|
||||
mkdir -p ${D}${PTEST_PATH}/tests
|
||||
install -m 0755 ${B}/tests/.libs/* ${D}${PTEST_PATH}/tests
|
||||
install -m 0644 ${S}/tests/confdir ${D}${PTEST_PATH}/tests
|
||||
}
|
||||
|
||||
pkg_postinst:${PN}() {
|
||||
if [ -z "$D" ] && [ -e /etc/init.d/populate-volatile.sh ] ; then
|
||||
/etc/init.d/populate-volatile.sh update
|
||||
fi
|
||||
}
|
||||
|
||||
inherit features_check
|
||||
ANY_OF_DISTRO_FEATURES = "pam systemd"
|
||||
|
||||
BBCLASSEXTEND = "nativesdk native"
|
||||
|
||||
CONFFILES:${PN}-runtime += "${sysconfdir}/pam.d/common-session"
|
||||
CONFFILES:${PN}-runtime += "${sysconfdir}/pam.d/common-auth"
|
||||
CONFFILES:${PN}-runtime += "${sysconfdir}/pam.d/common-password"
|
||||
CONFFILES:${PN}-runtime += "${sysconfdir}/pam.d/common-session-noninteractive"
|
||||
CONFFILES:${PN}-runtime += "${sysconfdir}/pam.d/common-account"
|
||||
CONFFILES:${PN}-runtime += "${sysconfdir}/security/limits.conf"
|
||||
|
||||
GITHUB_BASE_URI = "https://github.com/linux-pam/linux-pam/releases"
|
||||
|
||||
CVE_PRODUCT = "linux-pam"
|
||||
Reference in New Issue
Block a user