Compare commits

...

10 Commits

Author SHA1 Message Date
openeuler-ci-bot
cb3d588aab
!126 [sync] PR-125: 同步社区补丁
From: @openeuler-sync-bot 
Reviewed-by: @HuaxinLuGitee 
Signed-off-by: @HuaxinLuGitee
2024-02-19 01:45:37 +00:00
z30023234
5d22cefb4a backport some patches
(cherry picked from commit 76c1b9426d399c8f9a97f46779db76f409c7fbcc)
2024-02-05 20:57:22 +08:00
openeuler-ci-bot
a39ac0857e
!118 [sync] PR-115: backport some patches
From: @openeuler-sync-bot 
Reviewed-by: @HuaxinLuGitee 
Signed-off-by: @HuaxinLuGitee
2023-11-21 10:51:32 +00:00
qsw33
40d22c3533 backport some patches
(cherry picked from commit 6f859a83e8b96a406cdbdd0b679bc4009f870183)
2023-11-13 22:38:12 +08:00
openeuler-ci-bot
e87e6f3ee4
!106 backport some patches
From: @yunjia_w 
Reviewed-by: @HuaxinLuGitee 
Signed-off-by: @HuaxinLuGitee
2023-09-20 17:58:44 +00:00
yunjia_w
cca2696f61 backport some patches
Signed-off-by: yunjia_w <yunjia.wang@huawei.com>
2023-09-20 15:38:25 +08:00
openeuler-ci-bot
1672323b04
!99 backport some patches
From: @yunjia_w 
Reviewed-by: @HuaxinLuGitee 
Signed-off-by: @HuaxinLuGitee
2023-08-22 09:02:17 +00:00
yunjia_w
69dfb82329 backport some patches
Signed-off-by: yunjia_w <yunjia.wang@huawei.com>
2023-08-22 11:22:12 +08:00
openeuler-ci-bot
63fe17d2e5
!96 [sync] PR-94: shadow: Remove encrypted passwd for useradd-groupadd-groupmod-usermod
From: @openeuler-sync-bot 
Reviewed-by: @HuaxinLuGitee 
Signed-off-by: @HuaxinLuGitee
2023-08-17 06:10:10 +00:00
xiongshenglan
924aeaf613 shadow: Remove encrypted passwd for useradd-groupadd-groupmod-usermod
Remove encrypted passwd for useradd/groupadd/groupmod/usermod In groupadd/useradd, p parameter does not meet password complexity checks. Do not satisfy security requirements.
use CONFIG_SHADOW_REMOVE_POPTION

Signed-off-by: xiongshenglan <xiongshenglan@huawei.com>
(cherry picked from commit 424c34da00bcc050173c37de9e36a576518c75db)
2023-08-15 14:17:10 +08:00
39 changed files with 3075 additions and 22 deletions

View File

@ -0,0 +1,29 @@
From eaebea55a495a56317ed85e959b3599f73c6bdf2 Mon Sep 17 00:00:00 2001
From: David Michael <fedora.dm0@gmail.com>
Date: Sun, 23 Oct 2022 18:51:33 -0400
Subject: [PATCH] useradd: Fix buffer overflow when using a prefix
The buffer length did not count the string's trailing null byte.
Signed-off-by: David Michael <fedora.dm0@gmail.com>
Conflict: if(prefix[0]) There is no space after it.
Reference: https://github.com/shadow-maint/shadow/commit/f6f8bcd2a57c06983296485cc028ebdf467ebfd7
---
src/useradd.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/useradd.c b/src/useradd.c
index 39a744ee0..7ea0a9c4d 100644
--- a/src/useradd.c
+++ b/src/useradd.c
@@ -2372,7 +2372,7 @@ static void create_mail (void)
if (NULL == spool) {
spool = "/var/mail";
}
- file = alloca (strlen (prefix) + strlen (spool) + strlen (user_name) + 2);
+ file = alloca (strlen (prefix) + strlen (spool) + strlen (user_name) + 3);
if(prefix[0])
sprintf (file, "%s/%s/%s", prefix, spool, user_name);
else

View File

@ -0,0 +1,28 @@
From aff4989d1acf3afc718813144658c295d8d10f20 Mon Sep 17 00:00:00 2001
From: Andy Zaugg <andy.zaugg@gmail.com>
Date: Mon, 20 Sep 2021 20:41:50 -0700
Subject: [PATCH] Added documentation around CREATE_MAIL_SPOOL
Adding documentation aroud the parameter CREATE_MAIL_SPOOL in the
/etc/default/useradd file
Conflict: NA
Reference: https://github.com/shadow-maint/shadow/commit/aff4989d1acf3afc718813144658c295d8d10f20
---
man/login.defs.d/MAIL_DIR.xml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/man/login.defs.d/MAIL_DIR.xml b/man/login.defs.d/MAIL_DIR.xml
index 60b82d6b1..b5adb888b 100644
--- a/man/login.defs.d/MAIL_DIR.xml
+++ b/man/login.defs.d/MAIL_DIR.xml
@@ -35,6 +35,8 @@
The mail spool directory. This is needed to manipulate the mailbox
when its corresponding user account is modified or deleted. If not
specified, a compile-time default is used.
+ The parameter CREATE_MAIL_SPOOL in <filename>/etc/default/useradd</filename>
+ determines whether the mail spool should be created.
</para>
</listitem>
</varlistentry><varlistentry>

View File

@ -0,0 +1,46 @@
From 6cbec2d0aa29d6d25e9eed007ded4e79eb637519 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Fri, 5 Aug 2022 17:57:29 +0200
Subject: [PATCH] Address minor compiler warnings
copydir.c:666:44: warning: unsigned conversion from 'int' to '__mode_t' {aka 'unsigned int'} changes value from '-4096' to '4294963200' [-Wsign-conversion]
666 | if ( (mknod (dst, statp->st_mode & ~07777, statp->st_rdev) != 0)
| ^
copydir.c:116:1: warning: missing initializer for field 'quote' of 'struct error_context' [-Wmissing-field-initializers]
116 | };
| ^
In file included from copydir.c:27:
/usr/include/attr/error_context.h:30:23: note: 'quote' declared here
30 | const char *(*quote) (struct error_context *, const char *);
| ^~~~~
Conflict: NA
Reference: https://github.com/shadow-maint/shadow/commit/6cbec2d0aa29d6d25e9eed007ded4e79eb637519
---
libmisc/copydir.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libmisc/copydir.c b/libmisc/copydir.c
index 95042187b..e753d7cf0 100644
--- a/libmisc/copydir.c
+++ b/libmisc/copydir.c
@@ -112,7 +112,7 @@ static void error_acl (unused struct error_context *ctx, const char *fmt, ...)
}
static struct error_context ctx = {
- error_acl
+ error_acl, NULL, NULL
};
#endif /* WITH_ACL || WITH_ATTR */
@@ -663,7 +663,7 @@ static int copy_special (const char *src, const char *dst,
}
#endif /* WITH_SELINUX */
- if ( (mknod (dst, statp->st_mode & ~07777, statp->st_rdev) != 0)
+ if ( (mknod (dst, statp->st_mode & ~07777U, statp->st_rdev) != 0)
|| (chown_if_needed (dst, statp,
old_uid, new_uid, old_gid, new_gid) != 0)
#ifdef WITH_ACL

View File

@ -0,0 +1,228 @@
From e9ae247cb14f977d8881f481488843b10665dba8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Fri, 5 Aug 2022 17:57:19 +0200
Subject: [PATCH] Avoid races in chown_tree()
Use *at() functions to pin the directory operating in to avoid being
redirected by unprivileged users replacing parts of paths by symlinks to
privileged files.
Conflict: NA
Reference: https://github.com/shadow-maint/shadow/commit/e9ae247cb14f977d8881f481488843b10665dba8
---
libmisc/chowndir.c | 130 +++++++++++++++++----------------------------
1 file changed, 49 insertions(+), 81 deletions(-)
diff --git a/libmisc/chowndir.c b/libmisc/chowndir.c
index 0edc3b609..d31618a56 100644
--- a/libmisc/chowndir.c
+++ b/libmisc/chowndir.c
@@ -17,45 +17,28 @@
#include "defines.h"
#include <fcntl.h>
#include <stdio.h>
-/*
- * chown_tree - change ownership of files in a directory tree
- *
- * chown_dir() walks a directory tree and changes the ownership
- * of all files owned by the provided user ID.
- *
- * Only files owned (resp. group-owned) by old_uid (resp. by old_gid)
- * will have their ownership (resp. group-ownership) modified, unless
- * old_uid (resp. old_gid) is set to -1.
- *
- * new_uid and new_gid can be set to -1 to indicate that no owner or
- * group-owner shall be changed.
- */
-int chown_tree (const char *root,
+#include <unistd.h>
+
+static int chown_tree_at (int at_fd,
+ const char *path,
uid_t old_uid,
uid_t new_uid,
gid_t old_gid,
gid_t new_gid)
{
- char *new_name;
- size_t new_name_len;
- int rc = 0;
- struct DIRECT *ent;
- struct stat sb;
DIR *dir;
+ const struct DIRECT *ent;
+ struct stat dir_sb;
+ int dir_fd, rc = 0;
- new_name = malloc (1024);
- if (NULL == new_name) {
+ dir_fd = openat (at_fd, path, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
+ if (dir_fd < 0) {
return -1;
}
- new_name_len = 1024;
- /*
- * Make certain the directory exists. This routine is called
- * directly by the invoker, or recursively.
- */
-
- if (access (root, F_OK) != 0) {
- free (new_name);
+ dir = fdopendir (dir_fd);
+ if (!dir) {
+ (void) close (dir_fd);
return -1;
}
@@ -65,68 +48,34 @@ int chown_tree (const char *root,
* recursively. If not, it is checked to see if an ownership
* shall be changed.
*/
-
- dir = opendir (root);
- if (NULL == dir) {
- free (new_name);
- return -1;
- }
-
while ((ent = readdir (dir))) {
- size_t ent_name_len;
uid_t tmpuid = (uid_t) -1;
gid_t tmpgid = (gid_t) -1;
+ struct stat ent_sb;
/*
* Skip the "." and ".." entries
*/
-
if ( (strcmp (ent->d_name, ".") == 0)
|| (strcmp (ent->d_name, "..") == 0)) {
continue;
}
- /*
- * Make the filename for both the source and the
- * destination files.
- */
-
- ent_name_len = strlen (root) + strlen (ent->d_name) + 2;
- if (ent_name_len > new_name_len) {
- /*@only@*/char *tmp = realloc (new_name, ent_name_len);
- if (NULL == tmp) {
- rc = -1;
- break;
- }
- new_name = tmp;
- new_name_len = ent_name_len;
- }
-
- (void) snprintf (new_name, new_name_len, "%s/%s", root, ent->d_name);
-
- /* Don't follow symbolic links! */
- if (LSTAT (new_name, &sb) == -1) {
- continue;
+ rc = fstatat (dirfd(dir), ent->d_name, &ent_sb, AT_SYMLINK_NOFOLLOW);
+ if (rc < 0) {
+ break;
}
- if (S_ISDIR (sb.st_mode) && !S_ISLNK (sb.st_mode)) {
-
+ if (S_ISDIR (ent_sb.st_mode)) {
/*
* Do the entire subdirectory.
*/
-
- rc = chown_tree (new_name, old_uid, new_uid,
- old_gid, new_gid);
+ rc = chown_tree_at (dirfd(dir), ent->d_name, old_uid, new_uid, old_gid, new_gid);
if (0 != rc) {
break;
}
}
-#ifndef HAVE_LCHOWN
- /* don't use chown (follows symbolic links!) */
- if (S_ISLNK (sb.st_mode)) {
- continue;
- }
-#endif
+
/*
* By default, the IDs are not changed (-1).
*
@@ -136,43 +85,62 @@ int chown_tree (const char *root,
* If the file is not group-owned by the group, the
* group-owner is not changed.
*/
- if (((uid_t) -1 == old_uid) || (sb.st_uid == old_uid)) {
+ if (((uid_t) -1 == old_uid) || (ent_sb.st_uid == old_uid)) {
tmpuid = new_uid;
}
- if (((gid_t) -1 == old_gid) || (sb.st_gid == old_gid)) {
+ if (((gid_t) -1 == old_gid) || (ent_sb.st_gid == old_gid)) {
tmpgid = new_gid;
}
if (((uid_t) -1 != tmpuid) || ((gid_t) -1 != tmpgid)) {
- rc = LCHOWN (new_name, tmpuid, tmpgid);
+ rc = fchownat (dirfd(dir), ent->d_name, tmpuid, tmpgid, AT_SYMLINK_NOFOLLOW);
if (0 != rc) {
break;
}
}
}
- free (new_name);
- (void) closedir (dir);
-
/*
* Now do the root of the tree
*/
-
- if ((0 == rc) && (stat (root, &sb) == 0)) {
+ if ((0 == rc) && (fstat (dirfd(dir), &dir_sb) == 0)) {
uid_t tmpuid = (uid_t) -1;
gid_t tmpgid = (gid_t) -1;
- if (((uid_t) -1 == old_uid) || (sb.st_uid == old_uid)) {
+ if (((uid_t) -1 == old_uid) || (dir_sb.st_uid == old_uid)) {
tmpuid = new_uid;
}
- if (((gid_t) -1 == old_gid) || (sb.st_gid == old_gid)) {
+ if (((gid_t) -1 == old_gid) || (dir_sb.st_gid == old_gid)) {
tmpgid = new_gid;
}
if (((uid_t) -1 != tmpuid) || ((gid_t) -1 != tmpgid)) {
- rc = LCHOWN (root, tmpuid, tmpgid);
+ rc = fchown (dirfd(dir), tmpuid, tmpgid);
}
} else {
rc = -1;
}
+ (void) closedir (dir);
+
return rc;
}
+/*
+ * chown_tree - change ownership of files in a directory tree
+ *
+ * chown_dir() walks a directory tree and changes the ownership
+ * of all files owned by the provided user ID.
+ *
+ * Only files owned (resp. group-owned) by old_uid (resp. by old_gid)
+ * will have their ownership (resp. group-ownership) modified, unless
+ * old_uid (resp. old_gid) is set to -1.
+ *
+ * new_uid and new_gid can be set to -1 to indicate that no owner or
+ * group-owner shall be changed.
+ */
+int chown_tree (const char *root,
+ uid_t old_uid,
+ uid_t new_uid,
+ gid_t old_gid,
+ gid_t new_gid)
+{
+ return chown_tree_at (AT_FDCWD, root, old_uid, new_uid, old_gid, new_gid);
+}

View File

@ -0,0 +1,657 @@
From faeab50e710131816b261de66141524898c2c487 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Fri, 5 Aug 2022 17:57:32 +0200
Subject: [PATCH] Avoid races in copy_tree()
Use *at() functions to pin the directory operating in to avoid being
redirected by unprivileged users replacing parts of paths by symlinks to
privileged files.
Introduce a path_info struct with the full path and dirfd and name
information for *at() functions, since the full path is needed for link
resolution, SELinux label lookup and ACL attributes.
Conflict: NA
Reference: https://github.com/shadow-maint/shadow/commit/faeab50e710131816b261de66141524898c2c487
---
libmisc/copydir.c | 330 ++++++++++++++++++++++++++++++----------------
1 file changed, 218 insertions(+), 112 deletions(-)
diff --git a/libmisc/copydir.c b/libmisc/copydir.c
index e753d7cf0..5605f6fe0 100644
--- a/libmisc/copydir.c
+++ b/libmisc/copydir.c
@@ -47,40 +47,43 @@ struct link_name {
};
static /*@exposed@*/struct link_name *links;
-static int copy_entry (const char *src, const char *dst,
+struct path_info {
+ const char *full_path;
+ int dirfd;
+ const char *name;
+};
+
+static int copy_entry (const struct path_info *src, const struct path_info *dst,
bool reset_selinux,
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid);
-static int copy_dir (const char *src, const char *dst,
+static int copy_dir (const struct path_info *src, const struct path_info *dst,
bool reset_selinux,
- const struct stat *statp, const struct timeval mt[],
+ const struct stat *statp, const struct timespec mt[],
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid);
static /*@null@*/char *readlink_malloc (const char *filename);
-static int copy_symlink (const char *src, const char *dst,
+static int copy_symlink (const struct path_info *src, const struct path_info *dst,
unused bool reset_selinux,
- const struct stat *statp, const struct timeval mt[],
+ const struct stat *statp, const struct timespec mt[],
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid);
-static int copy_hardlink (const char *dst,
+static int copy_hardlink (const struct path_info *dst,
unused bool reset_selinux,
struct link_name *lp);
-static int copy_special (const char *src, const char *dst,
+static int copy_special (const struct path_info *src, const struct path_info *dst,
bool reset_selinux,
- const struct stat *statp, const struct timeval mt[],
+ const struct stat *statp, const struct timespec mt[],
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid);
-static int copy_file (const char *src, const char *dst,
+static int copy_file (const struct path_info *src, const struct path_info *dst,
bool reset_selinux,
- const struct stat *statp, const struct timeval mt[],
+ const struct stat *statp, const struct timespec mt[],
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid);
-static int chown_if_needed (const char *dst, const struct stat *statp,
+static int chownat_if_needed (const struct path_info *dst, const struct stat *statp,
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid);
-static int lchown_if_needed (const char *dst, const struct stat *statp,
- uid_t old_uid, uid_t new_uid,
- gid_t old_gid, gid_t new_gid);
static int fchown_if_needed (int fdst, const struct stat *statp,
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid);
@@ -116,6 +119,57 @@ static struct error_context ctx = {
};
#endif /* WITH_ACL || WITH_ATTR */
+#ifdef WITH_ACL
+static int perm_copy_path(const struct path_info *src,
+ const struct path_info *dst,
+ struct error_context *errctx)
+{
+ int src_fd, dst_fd, ret;
+
+ src_fd = openat(src->dirfd, src->name, O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
+ if (src_fd < 0) {
+ return -1;
+ }
+
+ dst_fd = openat(dst->dirfd, dst->name, O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
+ if (dst_fd < 0) {
+ (void) close (src_fd);
+ return -1;
+ }
+
+ ret = perm_copy_fd(src->full_path, src_fd, dst->full_path, dst_fd, errctx);
+ (void) close (src_fd);
+ (void) close (dst_fd);
+ return ret;
+}
+#endif /* WITH_ACL */
+
+#ifdef WITH_ATTR
+static int attr_copy_path(const struct path_info *src,
+ const struct path_info *dst,
+ int (*callback) (const char *, struct error_context *),
+ struct error_context *errctx)
+{
+ int src_fd, dst_fd, ret;
+
+ src_fd = openat(src->dirfd, src->name, O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
+ if (src_fd < 0) {
+ return -1;
+ }
+
+ dst_fd = openat(dst->dirfd, dst->name, O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
+ if (dst_fd < 0) {
+ (void) close (src_fd);
+ return -1;
+ }
+
+ ret = attr_copy_fd(src->full_path, src_fd, dst->full_path, dst_fd, callback, errctx);
+ (void) close (src_fd);
+ (void) close (dst_fd);
+ return ret;
+}
+#endif /* WITH_ATTR */
+
/*
* remove_link - delete a link from the linked list
*/
@@ -188,51 +242,36 @@ static /*@exposed@*/ /*@null@*/struct link_name *check_link (const char *name, c
return NULL;
}
-/*
- * copy_tree - copy files in a directory tree
- *
- * copy_tree() walks a directory tree and copies ordinary files
- * as it goes.
- *
- * When reset_selinux is enabled, extended attributes (and thus
- * SELinux attributes) are not copied.
- *
- * old_uid and new_uid are used to set the ownership of the copied
- * files. Unless old_uid is set to -1, only the files owned by
- * old_uid have their ownership changed to new_uid. In addition, if
- * new_uid is set to -1, no ownership will be changed.
- *
- * The same logic applies for the group-ownership and
- * old_gid/new_gid.
- */
-int copy_tree (const char *src_root, const char *dst_root,
+static int copy_tree_impl (const struct path_info *src, const struct path_info *dst,
bool copy_root, bool reset_selinux,
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid)
{
- int err = 0;
+ int dst_fd, src_fd, err = 0;
bool set_orig = false;
- struct DIRECT *ent;
+ const struct DIRECT *ent;
DIR *dir;
if (copy_root) {
struct stat sb;
- if (access (dst_root, F_OK) == 0) {
+
+ if ( fstatat (dst->dirfd, dst->name, &sb, 0) == 0
+ || errno != ENOENT) {
return -1;
}
- if (lstat (src_root, &sb) == -1) {
+ if (fstatat (src->dirfd, src->name, &sb, AT_SYMLINK_NOFOLLOW) == -1) {
return -1;
}
if (!S_ISDIR (sb.st_mode)) {
fprintf (shadow_logfd,
"%s: %s is not a directory",
- Prog, src_root);
+ Prog, src->full_path);
return -1;
}
- return copy_entry (src_root, dst_root, reset_selinux,
+ return copy_entry (src, dst, reset_selinux,
old_uid, new_uid, old_gid, new_gid);
}
@@ -242,8 +281,14 @@ int copy_tree (const char *src_root, const char *dst_root,
* target is created. It assumes the target directory exists.
*/
- if ( (access (src_root, F_OK) != 0)
- || (access (dst_root, F_OK) != 0)) {
+ src_fd = openat (src->dirfd, src->name, O_DIRECTORY | O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
+ if (src_fd < 0) {
+ return -1;
+ }
+
+ dst_fd = openat (dst->dirfd, dst->name, O_DIRECTORY | O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
+ if (dst_fd < 0) {
+ (void) close (src_fd);
return -1;
}
@@ -254,14 +299,16 @@ int copy_tree (const char *src_root, const char *dst_root,
* regular files (and directories ...) are copied, and no file
* is made set-ID.
*/
- dir = opendir (src_root);
+ dir = fdopendir (src_fd);
if (NULL == dir) {
+ (void) close (src_fd);
+ (void) close (dst_fd);
return -1;
}
if (src_orig == NULL) {
- src_orig = src_root;
- dst_orig = dst_root;
+ src_orig = src->full_path;
+ dst_orig = dst->full_path;
set_orig = true;
}
while ((0 == err) && (ent = readdir (dir)) != NULL) {
@@ -274,8 +321,8 @@ int copy_tree (const char *src_root, const char *dst_root,
char *dst_name;
size_t src_len = strlen (ent->d_name) + 2;
size_t dst_len = strlen (ent->d_name) + 2;
- src_len += strlen (src_root);
- dst_len += strlen (dst_root);
+ src_len += strlen (src->full_path);
+ dst_len += strlen (dst->full_path);
src_name = (char *) malloc (src_len);
dst_name = (char *) malloc (dst_len);
@@ -287,12 +334,22 @@ int copy_tree (const char *src_root, const char *dst_root,
* Build the filename for both the source and
* the destination files.
*/
+ struct path_info src_entry, dst_entry;
+
(void) snprintf (src_name, src_len, "%s/%s",
- src_root, ent->d_name);
+ src->full_path, ent->d_name);
(void) snprintf (dst_name, dst_len, "%s/%s",
- dst_root, ent->d_name);
+ dst->full_path, ent->d_name);
+
+ src_entry.full_path = src_name;
+ src_entry.dirfd = dirfd(dir);
+ src_entry.name = ent->d_name;
- err = copy_entry (src_name, dst_name,
+ dst_entry.full_path = dst_name;
+ dst_entry.dirfd = dst_fd;
+ dst_entry.name = ent->d_name;
+
+ err = copy_entry (&src_entry, &dst_entry,
reset_selinux,
old_uid, new_uid,
old_gid, new_gid);
@@ -306,6 +363,7 @@ int copy_tree (const char *src_root, const char *dst_root,
}
}
(void) closedir (dir);
+ (void) close (dst_fd);
if (set_orig) {
src_orig = NULL;
@@ -352,7 +410,7 @@ int copy_tree (const char *src_root, const char *dst_root,
* old_gid) will be modified, unless old_uid (resp. old_gid) is set
* to -1.
*/
-static int copy_entry (const char *src, const char *dst,
+static int copy_entry (const struct path_info *src, const struct path_info *dst,
bool reset_selinux,
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid)
@@ -360,32 +418,32 @@ static int copy_entry (const char *src, const char *dst,
int err = 0;
struct stat sb;
struct link_name *lp;
- struct timeval mt[2];
+ struct timespec mt[2];
- if (lstat (src, &sb) == -1) {
+ if (fstatat(src->dirfd, src->name, &sb, AT_SYMLINK_NOFOLLOW) == -1) {
/* If we cannot stat the file, do not care. */
} else {
#ifdef HAVE_STRUCT_STAT_ST_ATIM
mt[0].tv_sec = sb.st_atim.tv_sec;
- mt[0].tv_usec = sb.st_atim.tv_nsec / 1000;
+ mt[0].tv_nsec = sb.st_atim.tv_nsec;
#else /* !HAVE_STRUCT_STAT_ST_ATIM */
mt[0].tv_sec = sb.st_atime;
# ifdef HAVE_STRUCT_STAT_ST_ATIMENSEC
- mt[0].tv_usec = sb.st_atimensec / 1000;
+ mt[0].tv_nsec = sb.st_atimensec;
# else /* !HAVE_STRUCT_STAT_ST_ATIMENSEC */
- mt[0].tv_usec = 0;
+ mt[0].tv_nsec = 0;
# endif /* !HAVE_STRUCT_STAT_ST_ATIMENSEC */
#endif /* !HAVE_STRUCT_STAT_ST_ATIM */
#ifdef HAVE_STRUCT_STAT_ST_MTIM
mt[1].tv_sec = sb.st_mtim.tv_sec;
- mt[1].tv_usec = sb.st_mtim.tv_nsec / 1000;
+ mt[1].tv_nsec = sb.st_mtim.tv_nsec;
#else /* !HAVE_STRUCT_STAT_ST_MTIM */
mt[1].tv_sec = sb.st_mtime;
# ifdef HAVE_STRUCT_STAT_ST_MTIMENSEC
- mt[1].tv_usec = sb.st_mtimensec / 1000;
+ mt[1].tv_nsec = sb.st_mtimensec;
# else /* !HAVE_STRUCT_STAT_ST_MTIMENSEC */
- mt[1].tv_usec = 0;
+ mt[1].tv_nsec = 0;
# endif /* !HAVE_STRUCT_STAT_ST_MTIMENSEC */
#endif /* !HAVE_STRUCT_STAT_ST_MTIM */
@@ -407,7 +465,7 @@ static int copy_entry (const char *src, const char *dst,
* See if this is a previously copied link
*/
- else if ((lp = check_link (src, &sb)) != NULL) {
+ else if ((lp = check_link (src->full_path, &sb)) != NULL) {
err = copy_hardlink (dst, reset_selinux, lp);
}
@@ -446,9 +504,9 @@ static int copy_entry (const char *src, const char *dst,
*
* Return 0 on success, -1 on error.
*/
-static int copy_dir (const char *src, const char *dst,
+static int copy_dir (const struct path_info *src, const struct path_info *dst,
bool reset_selinux,
- const struct stat *statp, const struct timeval mt[],
+ const struct stat *statp, const struct timespec mt[],
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid)
{
@@ -460,15 +518,15 @@ static int copy_dir (const char *src, const char *dst,
*/
#ifdef WITH_SELINUX
- if (set_selinux_file_context (dst, S_IFDIR) != 0) {
+ if (set_selinux_file_context (dst->full_path, S_IFDIR) != 0) {
return -1;
}
#endif /* WITH_SELINUX */
- if ( (mkdir (dst, statp->st_mode) != 0)
- || (chown_if_needed (dst, statp,
+ if ( (mkdirat (dst->dirfd, dst->name, statp->st_mode) != 0)
+ || (chownat_if_needed (dst, statp,
old_uid, new_uid, old_gid, new_gid) != 0)
#ifdef WITH_ACL
- || ( (perm_copy_file (src, dst, &ctx) != 0)
+ || ( (perm_copy_path (src, dst, &ctx) != 0)
&& (errno != 0))
#else /* !WITH_ACL */
|| (chmod (dst, statp->st_mode) != 0)
@@ -482,12 +540,12 @@ static int copy_dir (const char *src, const char *dst,
* additional logic so that no unexpected permissions result.
*/
|| ( !reset_selinux
- && (attr_copy_file (src, dst, NULL, &ctx) != 0)
+ && (attr_copy_path (src, dst, NULL, &ctx) != 0)
&& (errno != 0))
#endif /* WITH_ATTR */
- || (copy_tree (src, dst, false, reset_selinux,
+ || (copy_tree_impl (src, dst, false, reset_selinux,
old_uid, new_uid, old_gid, new_gid) != 0)
- || (utimes (dst, mt) != 0)) {
+ || (utimensat (dst->dirfd, dst->name, mt, AT_SYMLINK_NOFOLLOW) != 0)) {
err = -1;
}
@@ -540,9 +598,9 @@ static /*@null@*/char *readlink_malloc (const char *filename)
*
* Return 0 on success, -1 on error.
*/
-static int copy_symlink (const char *src, const char *dst,
+static int copy_symlink (const struct path_info *src, const struct path_info *dst,
unused bool reset_selinux,
- const struct stat *statp, const struct timeval mt[],
+ const struct stat *statp, const struct timespec mt[],
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid)
{
@@ -560,7 +618,7 @@ static int copy_symlink (const char *src, const char *dst,
* destination directory name.
*/
- oldlink = readlink_malloc (src);
+ oldlink = readlink_malloc (src->full_path);
if (NULL == oldlink) {
return -1;
}
@@ -580,13 +638,13 @@ static int copy_symlink (const char *src, const char *dst,
}
#ifdef WITH_SELINUX
- if (set_selinux_file_context (dst, S_IFLNK) != 0) {
+ if (set_selinux_file_context (dst->full_path, S_IFLNK) != 0) {
free (oldlink);
return -1;
}
#endif /* WITH_SELINUX */
- if ( (symlink (oldlink, dst) != 0)
- || (lchown_if_needed (dst, statp,
+ if ( (symlinkat (oldlink, dst->dirfd, dst->name) != 0)
+ || (chownat_if_needed (dst, statp,
old_uid, new_uid, old_gid, new_gid) != 0)) {
/* FIXME: there are no modes on symlinks, right?
* ACL could be copied, but this would be much more
@@ -600,14 +658,9 @@ static int copy_symlink (const char *src, const char *dst,
}
free (oldlink);
-#ifdef HAVE_LUTIMES
- /* 2007-10-18: We don't care about
- * exit status of lutimes because
- * it returns ENOSYS on many system
- * - not implemented
- */
- (void) lutimes (dst, mt);
-#endif /* HAVE_LUTIMES */
+ if (utimensat (dst->dirfd, dst->name, mt, AT_SYMLINK_NOFOLLOW) != 0) {
+ return -1;
+ }
return 0;
}
@@ -619,13 +672,13 @@ static int copy_symlink (const char *src, const char *dst,
*
* Return 0 on success, -1 on error.
*/
-static int copy_hardlink (const char *dst,
+static int copy_hardlink (const struct path_info *dst,
unused bool reset_selinux,
struct link_name *lp)
{
/* FIXME: selinux, ACL, Extended Attributes needed? */
- if (link (lp->ln_name, dst) != 0) {
+ if (linkat (AT_FDCWD, lp->ln_name, dst->dirfd, dst->name, 0) != 0) {
return -1;
}
@@ -649,28 +702,28 @@ static int copy_hardlink (const char *dst,
*
* Return 0 on success, -1 on error.
*/
-static int copy_special (const char *src, const char *dst,
+static int copy_special (const struct path_info *src, const struct path_info *dst,
bool reset_selinux,
- const struct stat *statp, const struct timeval mt[],
+ const struct stat *statp, const struct timespec mt[],
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid)
{
int err = 0;
#ifdef WITH_SELINUX
- if (set_selinux_file_context (dst, statp->st_mode & S_IFMT) != 0) {
+ if (set_selinux_file_context (dst->full_path, statp->st_mode & S_IFMT) != 0) {
return -1;
}
#endif /* WITH_SELINUX */
- if ( (mknod (dst, statp->st_mode & ~07777U, statp->st_rdev) != 0)
- || (chown_if_needed (dst, statp,
+ if ( (mknodat (dst->dirfd, dst->name, statp->st_mode & ~07777U, statp->st_rdev) != 0)
+ || (chownat_if_needed (dst, statp,
old_uid, new_uid, old_gid, new_gid) != 0)
#ifdef WITH_ACL
- || ( (perm_copy_file (src, dst, &ctx) != 0)
+ || ( (perm_copy_path (src, dst, &ctx) != 0)
&& (errno != 0))
#else /* !WITH_ACL */
- || (chmod (dst, statp->st_mode & 07777) != 0)
+ || (fchmodat (dst->dirfd, dst->name, statp->st_mode & 07777, AT_SYMLINK_NOFOLLOW) != 0)
#endif /* !WITH_ACL */
#ifdef WITH_ATTR
/*
@@ -681,10 +734,10 @@ static int copy_special (const char *src, const char *dst,
* additional logic so that no unexpected permissions result.
*/
|| ( !reset_selinux
- && (attr_copy_file (src, dst, NULL, &ctx) != 0)
+ && (attr_copy_path (src, dst, NULL, &ctx) != 0)
&& (errno != 0))
#endif /* WITH_ATTR */
- || (utimes (dst, mt) != 0)) {
+ || (utimensat (dst->dirfd, dst->name, mt, AT_SYMLINK_NOFOLLOW) != 0)) {
err = -1;
}
@@ -737,9 +790,9 @@ static ssize_t full_write(int fd, const void *buf, size_t count) {
*
* Return 0 on success, -1 on error.
*/
-static int copy_file (const char *src, const char *dst,
+static int copy_file (const struct path_info *src, const struct path_info *dst,
bool reset_selinux,
- const struct stat *statp, const struct timeval mt[],
+ const struct stat *statp, const struct timespec mt[],
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid)
{
@@ -747,22 +800,22 @@ static int copy_file (const char *src, const char *dst,
int ifd;
int ofd;
- ifd = open (src, O_RDONLY|O_NOFOLLOW);
+ ifd = openat (src->dirfd, src->name, O_RDONLY|O_NOFOLLOW|O_CLOEXEC);
if (ifd < 0) {
return -1;
}
#ifdef WITH_SELINUX
- if (set_selinux_file_context (dst, S_IFREG) != 0) {
+ if (set_selinux_file_context (dst->full_path, S_IFREG) != 0) {
(void) close (ifd);
return -1;
}
#endif /* WITH_SELINUX */
- ofd = open (dst, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC | O_NOFOLLOW | O_CLOEXEC, statp->st_mode & 07777);
+ ofd = openat (dst->dirfd, dst->name, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC | O_NOFOLLOW | O_CLOEXEC, statp->st_mode & 07777);
if ( (ofd < 0)
|| (fchown_if_needed (ofd, statp,
old_uid, new_uid, old_gid, new_gid) != 0)
#ifdef WITH_ACL
- || ( (perm_copy_fd (src, ifd, dst, ofd, &ctx) != 0)
+ || ( (perm_copy_fd (src->full_path, ifd, dst->full_path, ofd, &ctx) != 0)
&& (errno != 0))
#else /* !WITH_ACL */
|| (fchmod (ofd, statp->st_mode & 07777) != 0)
@@ -776,7 +829,7 @@ static int copy_file (const char *src, const char *dst,
* additional logic so that no unexpected permissions result.
*/
|| ( !reset_selinux
- && (attr_copy_fd (src, ifd, dst, ofd, NULL, &ctx) != 0)
+ && (attr_copy_fd (src->full_path, ifd, dst->full_path, ofd, NULL, &ctx) != 0)
&& (errno != 0))
#endif /* WITH_ATTR */
) {
@@ -812,23 +865,13 @@ static int copy_file (const char *src, const char *dst,
}
(void) close (ifd);
-
-#ifdef HAVE_FUTIMES
- if (futimes (ofd, mt) != 0) {
- (void) close (ofd);
- return -1;
- }
-#endif /* HAVE_FUTIMES */
-
if (close (ofd) != 0) {
return -1;
}
-#ifndef HAVE_FUTIMES
- if (utimes(dst, mt) != 0) {
+ if (utimensat (dst->dirfd, dst->name, mt, AT_SYMLINK_NOFOLLOW) != 0) {
return -1;
}
-#endif /* !HAVE_FUTIMES */
return err;
}
@@ -863,7 +906,70 @@ static int chown_function ## _if_needed (type_dst dst, \
return chown_function (dst, tmpuid, tmpgid); \
}
-def_chown_if_needed (chown, const char *)
-def_chown_if_needed (lchown, const char *)
def_chown_if_needed (fchown, int)
+static int chownat_if_needed (const struct path_info *dst,
+ const struct stat *statp,
+ uid_t old_uid, uid_t new_uid,
+ gid_t old_gid, gid_t new_gid)
+{
+ uid_t tmpuid = (uid_t) -1;
+ gid_t tmpgid = (gid_t) -1;
+
+ /* Use new_uid if old_uid is set to -1 or if the file was
+ * owned by the user. */
+ if (((uid_t) -1 == old_uid) || (statp->st_uid == old_uid)) {
+ tmpuid = new_uid;
+ }
+ /* Otherwise, or if new_uid was set to -1, we keep the same
+ * owner. */
+ if ((uid_t) -1 == tmpuid) {
+ tmpuid = statp->st_uid;
+ }
+
+ if (((gid_t) -1 == old_gid) || (statp->st_gid == old_gid)) {
+ tmpgid = new_gid;
+ }
+ if ((gid_t) -1 == tmpgid) {
+ tmpgid = statp->st_gid;
+ }
+
+ return fchownat (dst->dirfd, dst->name, tmpuid, tmpgid, AT_SYMLINK_NOFOLLOW);
+}
+
+/*
+ * copy_tree - copy files in a directory tree
+ *
+ * copy_tree() walks a directory tree and copies ordinary files
+ * as it goes.
+ *
+ * When reset_selinux is enabled, extended attributes (and thus
+ * SELinux attributes) are not copied.
+ *
+ * old_uid and new_uid are used to set the ownership of the copied
+ * files. Unless old_uid is set to -1, only the files owned by
+ * old_uid have their ownership changed to new_uid. In addition, if
+ * new_uid is set to -1, no ownership will be changed.
+ *
+ * The same logic applies for the group-ownership and
+ * old_gid/new_gid.
+ */
+int copy_tree (const char *src_root, const char *dst_root,
+ bool copy_root, bool reset_selinux,
+ uid_t old_uid, uid_t new_uid,
+ gid_t old_gid, gid_t new_gid)
+{
+ const struct path_info src = {
+ .full_path = src_root,
+ .dirfd = AT_FDCWD,
+ .name = src_root
+ };
+ const struct path_info dst = {
+ .full_path = dst_root,
+ .dirfd = AT_FDCWD,
+ .name = dst_root
+ };
+
+ return copy_tree_impl(&src, &dst, copy_root, reset_selinux,
+ old_uid, new_uid, old_gid, new_gid);
+}

View File

@ -0,0 +1,157 @@
From f6f8bcd2a57c06983296485cc028ebdf467ebfd7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Fri, 5 Aug 2022 17:57:22 +0200
Subject: [PATCH] Avoid races in remove_tree()
Use *at() functions to pin the directory operating in to avoid being
redirected by unprivileged users replacing parts of paths by symlinks to
privileged files.
Conflict: NA
Reference: https://github.com/shadow-maint/shadow/commit/f6f8bcd2a57c06983296485cc028ebdf467ebfd7
---
libmisc/remove_tree.c | 87 +++++++++++++++++++------------------------
1 file changed, 39 insertions(+), 48 deletions(-)
diff --git a/libmisc/remove_tree.c b/libmisc/remove_tree.c
index 04bc7fc4a..3d76b95e0 100644
--- a/libmisc/remove_tree.c
+++ b/libmisc/remove_tree.c
@@ -11,6 +11,7 @@
#ident "$Id$"
+#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -21,90 +22,80 @@
#include "prototypes.h"
#include "defines.h"
-/*
- * remove_tree - delete a directory tree
- *
- * remove_tree() walks a directory tree and deletes all the files
- * and directories.
- * At the end, it deletes the root directory itself.
- */
-
-int remove_tree (const char *root, bool remove_root)
+static int remove_tree_at (int at_fd, const char *path, bool remove_root)
{
- char *new_name = NULL;
- int err = 0;
- struct DIRECT *ent;
- struct stat sb;
DIR *dir;
+ const struct DIRECT *ent;
+ int dir_fd, rc = 0;
- /*
- * Open the source directory and read each entry. Every file
- * entry in the directory is copied with the UID and GID set
- * to the provided values. As an added security feature only
- * regular files (and directories ...) are copied, and no file
- * is made set-ID.
- */
- dir = opendir (root);
- if (NULL == dir) {
+ dir_fd = openat (at_fd, path, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
+ if (dir_fd < 0) {
+ return -1;
+ }
+
+ dir = fdopendir (dir_fd);
+ if (!dir) {
+ (void) close (dir_fd);
return -1;
}
+ /*
+ * Open the source directory and delete each entry.
+ */
while ((ent = readdir (dir))) {
- size_t new_len = strlen (root) + strlen (ent->d_name) + 2;
+ struct stat ent_sb;
/*
* Skip the "." and ".." entries
*/
-
if (strcmp (ent->d_name, ".") == 0 ||
strcmp (ent->d_name, "..") == 0) {
continue;
}
- /*
- * Make the filename for the current entry.
- */
-
- free (new_name);
- new_name = (char *) malloc (new_len);
- if (NULL == new_name) {
- err = -1;
+ rc = fstatat (dirfd(dir), ent->d_name, &ent_sb, AT_SYMLINK_NOFOLLOW);
+ if (rc < 0) {
break;
}
- (void) snprintf (new_name, new_len, "%s/%s", root, ent->d_name);
- if (LSTAT (new_name, &sb) == -1) {
- continue;
- }
- if (S_ISDIR (sb.st_mode)) {
+ if (S_ISDIR (ent_sb.st_mode)) {
/*
* Recursively delete this directory.
*/
- if (remove_tree (new_name, true) != 0) {
- err = -1;
+ if (remove_tree_at (dirfd(dir), ent->d_name, true) != 0) {
+ rc = -1;
break;
}
} else {
/*
* Delete the file.
*/
- if (unlink (new_name) != 0) {
- err = -1;
+ if (unlinkat (dirfd(dir), ent->d_name, 0) != 0) {
+ rc = -1;
break;
}
}
}
- if (NULL != new_name) {
- free (new_name);
- }
+
(void) closedir (dir);
- if (remove_root && (0 == err)) {
- if (rmdir (root) != 0) {
- err = -1;
+ if (remove_root && (0 == rc)) {
+ if (unlinkat (at_fd, path, AT_REMOVEDIR) != 0) {
+ rc = -1;
}
}
- return err;
+ return rc;
}
+/*
+ * remove_tree - delete a directory tree
+ *
+ * remove_tree() walks a directory tree and deletes all the files
+ * and directories.
+ * At the end, it deletes the root directory itself.
+ */
+int remove_tree (const char *root, bool remove_root)
+{
+ return remove_tree_at (AT_FDCWD, root, remove_root);
+}

View File

@ -0,0 +1,34 @@
From b4472167c2f5057d56686d3349a9b55fc508efe6 Mon Sep 17 00:00:00 2001
From: ed neville <ed@s5h.net>
Date: Fri, 31 Dec 2021 22:40:13 +0000
Subject: [PATCH] Adding nofollow to opens
Conflict: NA
Reference: https://github.com/shadow-maint/shadow/commit/b4472167c2f5057d56686d3349a9b55fc508efe6
---
libmisc/copydir.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libmisc/copydir.c b/libmisc/copydir.c
index f2130bcac..a296d925d 100644
--- a/libmisc/copydir.c
+++ b/libmisc/copydir.c
@@ -741,7 +741,7 @@ static int copy_file (const char *src, const char *dst,
char buf[1024];
ssize_t cnt;
- ifd = open (src, O_RDONLY);
+ ifd = open (src, O_RDONLY|O_NOFOLLOW);
if (ifd < 0) {
return -1;
}
@@ -751,7 +751,7 @@ static int copy_file (const char *src, const char *dst,
return -1;
}
#endif /* WITH_SELINUX */
- ofd = open (dst, O_WRONLY | O_CREAT | O_TRUNC, statp->st_mode & 07777);
+ ofd = open (dst, O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, statp->st_mode & 07777);
if ( (ofd < 0)
|| (fchown_if_needed (ofd, statp,
old_uid, new_uid, old_gid, new_gid) != 0)

View File

@ -0,0 +1,31 @@
From b422e3c31691412f0a5404d09f7b328477e23c48 Mon Sep 17 00:00:00 2001
From: Skyler Ferrante <sjf5462@rit.edu>
Date: Tue, 30 May 2023 15:00:12 -0400
Subject: [PATCH] Check if crypt_method null before dereferencing
Make sure crypto_method set before sha-rounds. Only affects newusers.
---
src/newusers.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/src/newusers.c b/src/newusers.c
index ae2224fc..d6b7c3c3 100644
--- a/src/newusers.c
+++ b/src/newusers.c
@@ -662,6 +662,13 @@ static void process_flags (int argc, char **argv)
case 's':
sflg = true;
bad_s = 0;
+
+ if (!crypt_method){
+ fprintf(stderr,
+ _("%s: Provide '--crypt-method'\n"),
+ Prog);
+ usage (EXIT_FAILURE);
+ }
#if defined(USE_SHA_CRYPT)
if ( ( ((0 == strcmp (crypt_method, "SHA256")) || (0 == strcmp (crypt_method, "SHA512")))
&& (0 == getlong(optarg, &sha_rounds)))) {
--
2.27.0

View File

@ -0,0 +1,28 @@
From 1d281273b149f2bb992d893d8ca9ffffddc95cc8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Fri, 5 Aug 2022 17:57:26 +0200
Subject: [PATCH] Fail if regular file pre-exists in copy_tree()
Similar to the default behavior of mkdir(2), symlink(2), link(2) and
mknod(2).
Conflict: NA
Reference: https://github.com/shadow-maint/shadow/commit/1d281273b149f2bb992d893d8ca9ffffddc95cc8
---
libmisc/copydir.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libmisc/copydir.c b/libmisc/copydir.c
index 648f562a1..90895cfb0 100644
--- a/libmisc/copydir.c
+++ b/libmisc/copydir.c
@@ -723,7 +723,7 @@ static int copy_file (const char *src, const char *dst,
return -1;
}
#endif /* WITH_SELINUX */
- ofd = open (dst, O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, statp->st_mode & 07777);
+ ofd = open (dst, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC | O_NOFOLLOW | O_CLOEXEC, statp->st_mode & 07777);
if ( (ofd < 0)
|| (fchown_if_needed (ofd, statp,
old_uid, new_uid, old_gid, new_gid) != 0)

View File

@ -0,0 +1,27 @@
From 049f9a7f6b320c728a6274299041e360381d7cd5 Mon Sep 17 00:00:00 2001
From: Andy Zaugg <andy.zaugg@gmail.com>
Date: Tue, 21 Sep 2021 21:51:10 -0700
Subject: [PATCH] Fix parentheses in configure.ac
Resolving issue https://github.com/shadow-maint/shadow/issues/419
Conflict: NA
Reference: https://github.com/shadow-maint/shadow/commit/049f9a7f6b320c728a6274299041e360381d7cd5
---
configure.ac | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/configure.ac b/configure.ac
index 994836bda..6cbb6bd27 100644
--- a/configure.ac
+++ b/configure.ac
@@ -345,7 +345,7 @@ if test "$with_sssd" = "yes"; then
[AC_MSG_ERROR([posix_spawn is needed for sssd support])])
fi
-AS_IF([test "$with_su" != "no"], AC_DEFINE(WITH_SU, 1, [Build with su])])
+AS_IF([test "$with_su" != "no"], AC_DEFINE(WITH_SU, 1, [Build with su]))
AM_CONDITIONAL([WITH_SU], [test "x$with_su" != "xno"])
dnl Check for some functions in libc first, only if not found check for

View File

@ -0,0 +1,37 @@
From 29da702491eea314b915ea9c7a83c9af80cf5797 Mon Sep 17 00:00:00 2001
From: Bernd Kuhls <bernd@kuhls.net>
Date: Sun, 9 Jul 2023 10:55:03 +0200
Subject: [PATCH] Fix yescrypt support
Fixes build error:
newusers.c: In function 'update_passwd':
newusers.c:433:21: error: 'sflg' undeclared (first use in this function); did you mean 'rflg'?
introduced by
https://github.com/shadow-maint/shadow/commit/5cd04d03f94622c12220d4a6352824af081b8531
which forgot to define sflg for these configure options:
--without-sha-crypt --without-bcrypt --with-yescrypt
Reference: https://github.com/shadow-maint/shadow/commit/29da702491eea314b915ea9c7a83c9af80cf5797
Conflict: NA
---
src/newusers.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/newusers.c b/src/newusers.c
index 7cb8434b..08f79798 100644
--- a/src/newusers.c
+++ b/src/newusers.c
@@ -60,7 +60,7 @@ static bool rflg = false; /* create a system account */
#ifndef USE_PAM
static /*@null@*//*@observer@*/char *crypt_method = NULL;
#define cflg (NULL != crypt_method)
-#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_SM3_CRYPT)
+#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_SM3_CRYPT) || defined(USE_YESCRYPT)
static bool sflg = false;
#endif
#ifdef USE_SHA_CRYPT
--
2.27.0

View File

@ -0,0 +1,34 @@
From 63a96706b1205f91c4a57de21ac56e996d270ff1 Mon Sep 17 00:00:00 2001
From: Tobias Stoeckmann <tobias@stoeckmann.org>
Date: Fri, 29 Oct 2021 19:44:46 +0200
Subject: [PATCH] Handle malformed lines in hushlogins file.
If a line in hushlogins file, e.g. /etc/hushlogins, starts with
'\0', then current code performs an out of boundary write.
If the line lacks a newline at the end, then another character is
overridden.
With strcspn both cases are solved.
Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
Conflict: NA
Reference: https://github.com/shadow-maint/shadow/commit/63a96706b1205f91c4a57de21ac56e996d270ff1
---
libmisc/hushed.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libmisc/hushed.c b/libmisc/hushed.c
index b71b99ce2..3c3adafca 100644
--- a/libmisc/hushed.c
+++ b/libmisc/hushed.c
@@ -90,7 +90,7 @@ bool hushed (const char *username)
return false;
}
for (found = false; !found && (fgets (buf, (int) sizeof buf, fp) == buf);) {
- buf[strlen (buf) - 1] = '\0';
+ buf[strcspn (buf, "\n")] = '\0';
found = (strcmp (buf, pw->pw_shell) == 0) ||
(strcmp (buf, pw->pw_name) == 0);
}

View File

@ -0,0 +1,62 @@
From 624d57c08caceed306212d24c2147f6273f3fc4b Mon Sep 17 00:00:00 2001
From: Tobias Stoeckmann <tobias@stoeckmann.org>
Date: Sun, 14 Nov 2021 12:01:32 +0100
Subject: [PATCH] Improve child error handling
Always set SIGCHLD handler to default, even if the caller of vipw has
set SIGCHLD to ignore. If SIGCHLD is ignored no zombie processes would
be created, which in turn could mean that kill is called with an already
recycled pid.
Proof of Concept:
1. Compile nochld:
--
#include <signal.h>
#include <unistd.h>
int main(void) {
char *argv[] = { "vipw", NULL };
signal(SIGCHLD, SIG_IGN);
execvp("vipw", argv);
return 1;
}
--
2. Run nochld
3. Suspend child vi, which suspends vipw too:
`kill -STOP childpid`
4. Kill vi:
`kill -9 childpid`
5. You can see with ps that childpid is no zombie but disappeared
6. Bring vipw back into foreground
`fg`
The kill call sends SIGCONT to "childpid" which in turn could have been
already recycled for another process.
This is definitely not a vulnerability. It would take super user
operations, at which point an attacker would have already elevated
permissions.
Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
Conflict: NA
Reference: https://github.com/shadow-maint/shadow/commit/624d57c08caceed306212d24c2147f6273f3fc4b
---
src/vipw.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/vipw.c b/src/vipw.c
index 94185c3df..1a69ef285 100644
--- a/src/vipw.c
+++ b/src/vipw.c
@@ -349,6 +349,9 @@ vipwedit (const char *file, int (*file_lock) (void), int (*file_unlock) (void))
sigprocmask(SIG_BLOCK, &mask, &omask);
}
+ /* set SIGCHLD to default for waitpid */
+ signal(SIGCHLD, SIG_DFL);
+
for (;;) {
pid = waitpid (pid, &status, WUNTRACED);
if ((pid != -1) && (WIFSTOPPED (status) != 0)) {

View File

@ -0,0 +1,98 @@
From f606314f0c22fb5d13e5af17a70860d57559e808 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Fri, 5 Aug 2022 17:57:27 +0200
Subject: [PATCH] More robust file content copy in copy_tree()
Bail out on read(2) failure, continue on EINTR, support short writes and
increase chunk size.
Conflict: NA
Reference: https://github.com/shadow-maint/shadow/commit/f606314f0c22fb5d13e5af17a70860d57559e808
---
libmisc/copydir.c | 58 +++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 54 insertions(+), 4 deletions(-)
diff --git a/libmisc/copydir.c b/libmisc/copydir.c
index 90895cfb0..95042187b 100644
--- a/libmisc/copydir.c
+++ b/libmisc/copydir.c
@@ -691,6 +691,42 @@ static int copy_special (const char *src, const char *dst,
return err;
}
+/*
+ * full_write - write entire buffer
+ *
+ * Write up to count bytes from the buffer starting at buf to the
+ * file referred to by the file descriptor fd.
+ * Retry in case of a short write.
+ *
+ * Returns the number of bytes written on success, -1 on error.
+ */
+static ssize_t full_write(int fd, const void *buf, size_t count) {
+ ssize_t written = 0;
+
+ while (count > 0) {
+ ssize_t res;
+
+ res = write(fd, buf, count);
+ if (res < 0) {
+ if (errno == EINTR) {
+ continue;
+ }
+
+ return res;
+ }
+
+ if (res == 0) {
+ break;
+ }
+
+ written += res;
+ buf = (const unsigned char*)buf + res;
+ count -= (size_t)res;
+ }
+
+ return written;
+}
+
/*
* copy_file - copy a file
*
@@ -710,8 +746,6 @@ static int copy_file (const char *src, const char *dst,
int err = 0;
int ifd;
int ofd;
- char buf[1024];
- ssize_t cnt;
ifd = open (src, O_RDONLY|O_NOFOLLOW);
if (ifd < 0) {
@@ -753,8 +787,24 @@ static int copy_file (const char *src, const char *dst,
return -1;
}
- while ((cnt = read (ifd, buf, sizeof buf)) > 0) {
- if (write (ofd, buf, (size_t)cnt) != cnt) {
+ while (true) {
+ char buf[8192];
+ ssize_t cnt;
+
+ cnt = read (ifd, buf, sizeof buf);
+ if (cnt < 0) {
+ if (errno == EINTR) {
+ continue;
+ }
+ (void) close (ofd);
+ (void) close (ifd);
+ return -1;
+ }
+ if (cnt == 0) {
+ break;
+ }
+
+ if (full_write (ofd, buf, (size_t)cnt) < 0) {
(void) close (ofd);
(void) close (ifd);
return -1;

View File

@ -0,0 +1,43 @@
From 117bc66c6f95fa85ca75ecfdb8fbd3615deca0b6 Mon Sep 17 00:00:00 2001
From: Michael Vetter <jubalh@iodoru.org>
Date: Mon, 20 Sep 2021 11:04:50 +0200
Subject: [PATCH] Only free sgent if it was initialized
`sgent` is only initialized in `get_group()` if `is_shadowgrp` is true.
So we should also only attempt to free it if this is actually the case.
Can otherwise lead to:
```
free() double free detected in tcache 2 (gpasswd)
```
Conflict: NA
Reference: https://github.com/shadow-maint/shadow/commit/117bc66c6f95fa85ca75ecfdb8fbd3615deca0b6
---
src/gpasswd.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/src/gpasswd.c b/src/gpasswd.c
index a43d9a590..04bed83d6 100644
--- a/src/gpasswd.c
+++ b/src/gpasswd.c
@@ -1207,11 +1207,13 @@ int main (int argc, char **argv)
sssd_flush_cache (SSSD_DB_GROUP);
#ifdef SHADOWGRP
- if (sgent.sg_adm) {
- xfree(sgent.sg_adm);
- }
- if (sgent.sg_mem) {
- xfree(sgent.sg_mem);
+ if (is_shadowgrp) {
+ if (sgent.sg_adm) {
+ xfree(sgent.sg_adm);
+ }
+ if (sgent.sg_mem) {
+ xfree(sgent.sg_mem);
+ }
}
#endif
if (grent.gr_mem) {

View File

@ -0,0 +1,42 @@
From 8175b1532e4bb1951264e8a6ee5f484137e5306c Mon Sep 17 00:00:00 2001
From: Tobias Stoeckmann <tobias@stoeckmann.org>
Date: Thu, 18 May 2023 17:25:35 +0200
Subject: [PATCH] Plug econf memory leaks
You can see the memory leaks with address sanitizer if shadow is
compiled with `--enable-vendordir=/usr/etc`.
How to reproduce:
1. Prepare a custom shell file as root
```
mkdir -p /etc/shells.d
echo /bin/myshell > /etc/shells.d/custom
```
2. Run chsh as regular user
```
chsh
```
Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
---
lib/getdef.c | 2 ++
1 files changed, 2 insertions(+)
diff --git a/lib/getdef.c b/lib/getdef.c
index a2a7e484..763d847a 100644
--- a/lib/getdef.c
+++ b/lib/getdef.c
@@ -522,6 +522,8 @@ static void def_load (void)
* syslog. The tools will just use their default values.
*/
(void)putdef_str (keys[i], value);
+
+ free(value);
}
econf_free (keys);
--
2.27.0

View File

@ -0,0 +1,148 @@
From dab764d0195fc16d1d39330eee8a33e8917826d8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Fri, 5 Aug 2022 17:57:24 +0200
Subject: [PATCH] Require symlink support
Require lstat(2), lchown(2), S_IFLNK and S_ISLNK from POSIX.1-2001.
Already unconditionally used in lib/tcbfuncs.c and lib/run_part.c.
Conflict: NA
Reference: https://github.com/shadow-maint/shadow/commit/dab764d0195fc16d1d39330eee8a33e8917826d8
---
configure.ac | 2 +-
lib/commonio.c | 2 --
lib/defines.h | 16 ----------------
libmisc/copydir.c | 10 ++--------
4 files changed, 3 insertions(+), 27 deletions(-)
diff --git a/configure.ac b/configure.ac
index b9a2263bb..7e954c29c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -53,7 +53,7 @@ AC_CHECK_HEADER([shadow.h],,[AC_MSG_ERROR([You need a libc with shadow.h])])
AC_CHECK_FUNCS(arc4random_buf l64a fchmod fchown fsync futimes getgroups \
gethostname getentropy getrandom getspnam gettimeofday getusershell \
- getutent initgroups lchown lckpwdf lstat lutimes memcpy memset \
+ getutent initgroups lckpwdf lutimes memcpy memset \
setgroups sigaction strchr updwtmp updwtmpx innetgr getpwnam_r \
getpwuid_r getgrnam_r getgrgid_r getspnam_r getaddrinfo ruserok \
dlopen)
diff --git a/lib/commonio.c b/lib/commonio.c
index 9e0fde600..80288d644 100644
--- a/lib/commonio.c
+++ b/lib/commonio.c
@@ -65,7 +65,6 @@ int lrename (const char *old, const char *new)
int res;
char *r = NULL;
-#if defined(S_ISLNK)
#ifndef __GLIBC__
char resolved_path[PATH_MAX];
#endif /* !__GLIBC__ */
@@ -82,7 +81,6 @@ int lrename (const char *old, const char *new)
new = r;
}
}
-#endif /* S_ISLNK */
res = rename (old, new);
diff --git a/lib/defines.h b/lib/defines.h
index 4a2b90c9e..ee33aa0da 100644
--- a/lib/defines.h
+++ b/lib/defines.h
@@ -205,22 +205,6 @@ static inline void memzero(void *ptr, size_t size)
# endif
#endif
-#ifndef S_ISLNK
-#define S_ISLNK(x) (0)
-#endif
-
-#if HAVE_LCHOWN
-#define LCHOWN lchown
-#else
-#define LCHOWN chown
-#endif
-
-#if HAVE_LSTAT
-#define LSTAT lstat
-#else
-#define LSTAT stat
-#endif
-
#if HAVE_TERMIOS_H
# include <termios.h>
# define STTY(fd, termio) tcsetattr(fd, TCSANOW, termio)
diff --git a/libmisc/copydir.c b/libmisc/copydir.c
index 2929151db..648f562a1 100644
--- a/libmisc/copydir.c
+++ b/libmisc/copydir.c
@@ -56,14 +56,12 @@ static int copy_dir (const char *src, const char *dst,
const struct stat *statp, const struct timeval mt[],
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid);
-#ifdef S_IFLNK
static /*@null@*/char *readlink_malloc (const char *filename);
static int copy_symlink (const char *src, const char *dst,
unused bool reset_selinux,
const struct stat *statp, const struct timeval mt[],
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid);
-#endif /* S_IFLNK */
static int copy_hardlink (const char *dst,
unused bool reset_selinux,
struct link_name *lp);
@@ -223,7 +221,7 @@ int copy_tree (const char *src_root, const char *dst_root,
return -1;
}
- if (LSTAT (src_root, &sb) == -1) {
+ if (lstat (src_root, &sb) == -1) {
return -1;
}
@@ -364,7 +362,7 @@ static int copy_entry (const char *src, const char *dst,
struct link_name *lp;
struct timeval mt[2];
- if (LSTAT (src, &sb) == -1) {
+ if (lstat (src, &sb) == -1) {
/* If we cannot stat the file, do not care. */
} else {
#ifdef HAVE_STRUCT_STAT_ST_ATIM
@@ -396,7 +394,6 @@ static int copy_entry (const char *src, const char *dst,
old_uid, new_uid, old_gid, new_gid);
}
-#ifdef S_IFLNK
/*
* Copy any symbolic links
*/
@@ -405,7 +402,6 @@ static int copy_entry (const char *src, const char *dst,
err = copy_symlink (src, dst, reset_selinux, &sb, mt,
old_uid, new_uid, old_gid, new_gid);
}
-#endif /* S_IFLNK */
/*
* See if this is a previously copied link
@@ -498,7 +494,6 @@ static int copy_dir (const char *src, const char *dst,
return err;
}
-#ifdef S_IFLNK
/*
* readlink_malloc - wrapper for readlink
*
@@ -616,7 +611,6 @@ static int copy_symlink (const char *src, const char *dst,
return 0;
}
-#endif /* S_IFLNK */
/*
* copy_hardlink - copy a hardlink

View File

@ -0,0 +1,36 @@
From 53a17c1742a4b5fcf9280fd6dd85fc77588535c2 Mon Sep 17 00:00:00 2001
From: Jeffrey Bencteux <jeffbencteux@gmail.com>
Date: Wed, 21 Jun 2023 15:12:43 +0200
Subject: [PATCH] chgpasswd: fix segfault in command-line options
Using the --sha-rounds option without first giving a crypt method via the --crypt-method option results in comparisons with a NULL pointer and thus make chgpasswd segfault:
$ chgpasswd -s 1
zsh: segmentation fault chgpasswd -s 1
Current patch add a sanity check before these comparisons to ensure there is a defined encryption method.
---
src/chgpasswd.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/src/chgpasswd.c b/src/chgpasswd.c
index fe4055d8..7b773e2f 100644
--- a/src/chgpasswd.c
+++ b/src/chgpasswd.c
@@ -186,6 +186,13 @@ static void process_flags (int argc, char **argv)
case 's':
sflg = true;
bad_s = 0;
+
+ if (!crypt_method) {
+ fprintf (stderr,
+ _("%s: no crypt method defined\n"),
+ Prog);
+ usage (E_USAGE);
+ }
#if defined(USE_SHA_CRYPT)
if ( ( ((0 == strcmp (crypt_method, "SHA256")) || (0 == strcmp (crypt_method, "SHA512")))
&& (0 == getlong(optarg, &sha_rounds)))) {
--
2.27.0

View File

@ -0,0 +1,97 @@
From 9cdb5251b6c30487a7d935a1a7827f493249479d Mon Sep 17 00:00:00 2001
From: juyin <zhuyan34@huawei.com>
Date: Sat, 2 Apr 2022 11:48:51 +0800
Subject: [PATCH] chpasswd: add IS_CRYPT_METHOD
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Use macro IS_CRYPT_METHOD instead of strcmp(crypt_method, xx)==0 to make the code more cleanup
Reference: https://github.com/shadow-maint/shadow/commit/9cdb5251b6c30487a7d935a1a7827f493249479d
Conflict: This patch is adapted to SM3.The pre-optimization of the get_salt function is not incorporated. Therefore, the modification related to the get_salt function is not incorporated in this patch.
---
src/chpasswd.c | 34 ++++++++++++++++++----------------
1 file changed, 18 insertions(+), 16 deletions(-)
diff --git a/src/chpasswd.c b/src/chpasswd.c
index 3b30c01..cc00180 100644
--- a/src/chpasswd.c
+++ b/src/chpasswd.c
@@ -52,6 +52,8 @@
/*@-exitarg@*/
#include "exitcodes.h"
+#define IS_CRYPT_METHOD(str) ((crypt_method != NULL && strcmp(crypt_method, str) == 0) ? true : false)
+
/*
* Global variables
*/
@@ -208,26 +210,26 @@ static void process_flags (int argc, char **argv)
sflg = true;
bad_s = 0;
#if defined(USE_SHA_CRYPT)
- if ( ( ((0 == strcmp (crypt_method, "SHA256")) || (0 == strcmp (crypt_method, "SHA512")))
- && (0 == getlong(optarg, &sha_rounds)))) {
+ if ((IS_CRYPT_METHOD("SHA256") || IS_CRYPT_METHOD("SHA512"))
+ && (0 == getlong(optarg, &sha_rounds))) {
bad_s = 1;
}
#endif /* USE_SHA_CRYPT */
#if defined(USE_BCRYPT)
- if (( (0 == strcmp (crypt_method, "BCRYPT"))
- && (0 == getlong(optarg, &bcrypt_rounds)))) {
+ if (IS_CRYPT_METHOD("BCRYPT")
+ && (0 == getlong(optarg, &bcrypt_rounds))) {
bad_s = 1;
}
#endif /* USE_BCRYPT */
#if defined(USE_YESCRYPT)
- if (( (0 == strcmp (crypt_method, "YESCRYPT"))
- && (0 == getlong(optarg, &yescrypt_cost)))) {
+ if (IS_CRYPT_METHOD("YESCRYPT")
+ && (0 == getlong(optarg, &yescrypt_cost))) {
bad_s = 1;
}
#endif /* USE_YESCRYPT */
#if defined(USE_SM3_CRYPT)
- if (( (0 == strcmp (crypt_method, "SM3"))
- && (0 == getlong(optarg, &sm3_rounds)))) {
+ if (IS_CRYPT_METHOD("SM3")
+ && (0 == getlong(optarg, &sm3_rounds))) {
bad_s = 1;
}
#endif /* USE_SM3_CRYPT */
@@ -275,21 +277,21 @@ static void check_flags (void)
}
if (cflg) {
- if ( (0 != strcmp (crypt_method, "DES"))
- && (0 != strcmp (crypt_method, "MD5"))
- && (0 != strcmp (crypt_method, "NONE"))
+ if ((!IS_CRYPT_METHOD("DES"))
+ &&(!IS_CRYPT_METHOD("MD5"))
+ &&(!IS_CRYPT_METHOD("NONE"))
#ifdef USE_SHA_CRYPT
- && (0 != strcmp (crypt_method, "SHA256"))
- && (0 != strcmp (crypt_method, "SHA512"))
+ &&(!IS_CRYPT_METHOD("SHA256"))
+ &&(!IS_CRYPT_METHOD("SHA512"))
#endif /* USE_SHA_CRYPT */
#ifdef USE_SM3_CRYPT
- && (0 != strcmp (crypt_method, "SM3"))
+ &&(!IS_CRYPT_METHOD("SM3"))
#endif /* USE_SM3_CRYPT */
#ifdef USE_BCRYPT
- && (0 != strcmp (crypt_method, "BCRYPT"))
+ &&(!IS_CRYPT_METHOD("BCRYPT"))
#endif /* USE_BCRYPT */
#ifdef USE_YESCRYPT
- && (0 != strcmp (crypt_method, "YESCRYPT"))
+ &&(!IS_CRYPT_METHOD("YESCRYPT"))
#endif /* USE_YESCRYPT */
) {
fprintf (stderr,
--
2.27.0

View File

@ -0,0 +1,31 @@
From 7321ceaf69a7028a04056e548d861b291634c2d0 Mon Sep 17 00:00:00 2001
From: Samanta Navarro <ferivoz@riseup.net>
Date: Thu, 18 May 2023 11:58:19 +0000
Subject: [PATCH] chsh: Verify that login shell path is absolute
The getusershell implementation of musl returns every line within the
/etc/shells file, which even includes comments. Only consider absolute
paths for login shells.
Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
---
src/chsh.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/chsh.c b/src/chsh.c
index 639ff630..d6eca6e3 100644
--- a/src/chsh.c
+++ b/src/chsh.c
@@ -574,7 +574,8 @@ int main (int argc, char **argv)
fail_exit (1);
}
if ( !amroot
- && ( is_restricted_shell (loginsh)
+ && ( loginsh[0] != '/'
+ || is_restricted_shell (loginsh)
|| (access (loginsh, X_OK) != 0))) {
fprintf (stderr, _("%s: %s is an invalid shell\n"), Prog, loginsh);
fail_exit (1);
--
2.27.0

View File

@ -0,0 +1,35 @@
From 419cf1f1c4721829c4d68c9e5fee112a5da5890f Mon Sep 17 00:00:00 2001
From: Serge Hallyn <serge@hallyn.com>
Date: Fri, 19 May 2023 14:49:04 -0500
Subject: [PATCH] def_load: avoid NULL deref
If econf_getStringValue() fails, it will return an error and
set value to NULL. Look for the error and avoid dereferencing
value in that case.
Signed-off-by: Serge Hallyn <serge@hallyn.com>
---
lib/getdef.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/lib/getdef.c b/lib/getdef.c
index 39cd62d5..8075821b 100644
--- a/lib/getdef.c
+++ b/lib/getdef.c
@@ -505,7 +505,12 @@ static void def_load (void)
for (size_t i = 0; i < key_number; i++) {
char *value;
- econf_getStringValue(defs_file, NULL, keys[i], &value);
+ error = econf_getStringValue(defs_file, NULL, keys[i], &value);
+ if (error) {
+ SYSLOG ((LOG_CRIT, "failed reading key %zu from econf [%s]",
+ i, econf_errString(error)));
+ exit (EXIT_FAILURE);
+ }
/*
* Store the value in def_table.
--
2.27.0

View File

@ -0,0 +1,142 @@
From 65c88a43a23c2391dcc90c0abda3e839e9c57904 Mon Sep 17 00:00:00 2001
From: Alejandro Colomar <alx@kernel.org>
Date: Sat, 10 Jun 2023 16:20:05 +0200
Subject: [PATCH] gpasswd(1): Fix password leak
How to trigger this password leak?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When gpasswd(1) asks for the new password, it asks twice (as is usual
for confirming the new password). Each of those 2 password prompts
uses agetpass() to get the password. If the second agetpass() fails,
the first password, which has been copied into the 'static' buffer
'pass' via STRFCPY(), wasn't being zeroed.
agetpass() is defined in <./libmisc/agetpass.c> (around line 91), and
can fail for any of the following reasons:
- malloc(3) or readpassphrase(3) failure.
These are going to be difficult to trigger. Maybe getting the system
to the limits of memory utilization at that exact point, so that the
next malloc(3) gets ENOMEM, and possibly even the OOM is triggered.
About readpassphrase(3), ENFILE and EINTR seem the only plausible
ones, and EINTR probably requires privilege or being the same user;
but I wouldn't discard ENFILE so easily, if a process starts opening
files.
- The password is longer than PASS_MAX.
The is plausible with physical access. However, at that point, a
keylogger will be a much simpler attack.
And, the attacker must be able to know when the second password is being
introduced, which is not going to be easy.
How to read the password after the leak?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Provoking the leak yourself at the right point by entering a very long
password is easy, and inspecting the process stack at that point should
be doable. Try to find some consistent patterns.
Then, search for those patterns in free memory, right after the victim
leaks their password.
Once you get the leak, a program should read all the free memory
searching for patterns that gpasswd(1) leaves nearby the leaked
password.
On 6/10/23 03:14, Seth Arnold wrote:
> An attacker process wouldn't be able to use malloc(3) for this task.
> There's a handful of tools available for userspace to allocate memory:
>
> - brk / sbrk
> - mmap MAP_ANONYMOUS
> - mmap /dev/zero
> - mmap some other file
> - shm_open
> - shmget
>
> Most of these return only pages of zeros to a process. Using mmap of an
> existing file, you can get some of the contents of the file demand-loaded
> into the memory space on the first use.
>
> The MAP_UNINITIALIZED flag only works if the kernel was compiled with
> CONFIG_MMAP_ALLOW_UNINITIALIZED. This is rare.
>
> malloc(3) doesn't zero memory, to our collective frustration, but all the
> garbage in the allocations is from previous allocations in the current
> process. It isn't leftover from other processes.
>
> The avenues available for reading the memory:
> - /dev/mem and /dev/kmem (requires root, not available with Secure Boot)
> - /proc/pid/mem (requires ptrace privileges, mediated by YAMA)
> - ptrace (requires ptrace privileges, mediated by YAMA)
> - causing memory to be swapped to disk, and then inspecting the swap
>
> These all require a certain amount of privileges.
How to fix it?
~~~~~~~~~~~~~~
memzero(), which internally calls explicit_bzero(3), or whatever
alternative the system provides with a slightly different name, will
make sure that the buffer is zeroed in memory, and optimizations are not
allowed to impede this zeroing.
This is not really 100% effective, since compilers may place copies of
the string somewhere hidden in the stack. Those copies won't get zeroed
by explicit_bzero(3). However, that's arguably a compiler bug, since
compilers should make everything possible to avoid optimizing strings
that are later passed to explicit_bzero(3). But we all know that
sometimes it's impossible to have perfect knowledge in the compiler, so
this is plausible. Nevertheless, there's nothing we can do against such
issues, except minimizing the time such passwords are stored in plain
text.
Security concerns
~~~~~~~~~~~~~~~~~
We believe this isn't easy to exploit. Nevertheless, and since the fix
is trivial, this fix should probably be applied soon, and backported to
all supported distributions, to prevent someone else having more
imagination than us to find a way.
Affected versions
~~~~~~~~~~~~~~~~~
All. Bug introduced in shadow 19990709. That's the second commit in
the git history.
Fixes: 45c6603cc86c ("[svn-upgrade] Integrating new upstream version, shadow (19990709)")
Reported-by: Alejandro Colomar <alx@kernel.org>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Seth Arnold <seth.arnold@canonical.com>
Cc: Christian Brauner <christian@brauner.io>
Cc: Balint Reczey <rbalint@debian.org>
Cc: Sam James <sam@gentoo.org>
Cc: David Runge <dvzrv@archlinux.org>
Cc: Andreas Jaeger <aj@suse.de>
Cc: <~hallyn/shadow@lists.sr.ht>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
---
src/gpasswd.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/gpasswd.c b/src/gpasswd.c
index 609fe0a4..3b76ff8e 100644
--- a/src/gpasswd.c
+++ b/src/gpasswd.c
@@ -898,6 +898,7 @@ static void change_passwd (struct group *gr)
strzero (cp);
cp = getpass (_("Re-enter new password: "));
if (NULL == cp) {
+ memzero (pass, sizeof pass);
exit (1);
}
--
2.27.0

View File

@ -0,0 +1,29 @@
From 54ab542887994f8b6e5411469d6867e3a2e58800 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Thu, 26 Jan 2023 21:03:56 +0100
Subject: [PATCH] lib/btrfs: avoid NULL-dereference
btrfs.c:42:13: warning: use of NULL 'cmd' where non-null expected [CWE-476] [-Wanalyzer-null-argument]
Reviewed-by: Alejandro Colomar <alx@kernel.org>
Conflict: NA
Reference: https://github.com/shadow-maint/shadow/commit/54ab542887994f8b6e5411469d6867e3a2e58800
---
libmisc/btrfs.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libmisc/btrfs.c b/libmisc/btrfs.c
index a2563f7c3..03915981c 100644
--- a/libmisc/btrfs.c
+++ b/libmisc/btrfs.c
@@ -39,7 +39,7 @@ static int run_btrfs_subvolume_cmd(const char *subcmd, const char *arg1, const c
NULL
};
- if (access(cmd, X_OK)) {
+ if (!cmd || access(cmd, X_OK)) {
return 1;
}

View File

@ -0,0 +1,70 @@
From d594243fbbdabc73fdee50886f6dd11867b5cfab Mon Sep 17 00:00:00 2001
From: Iker Pedrosa <ipedrosa@redhat.com>
Date: Thu, 18 Nov 2021 16:48:26 +0100
Subject: [PATCH] lib: check NULL before freeing passwd data
Add an additional NULL check condition in spw_free() and pw_free() to
avoid freeing an already empty pointer.
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
Conflict: NA
Reference: https://github.com/shadow-maint/shadow/commit/d594243fbbdabc73fdee50886f6dd11867b5cfab
---
lib/pwmem.c | 18 ++++++++++--------
lib/shadowmem.c | 12 +++++++-----
2 files changed, 17 insertions(+), 13 deletions(-)
diff --git a/lib/pwmem.c b/lib/pwmem.c
index 17d2eb219..9f184d5e1 100644
--- a/lib/pwmem.c
+++ b/lib/pwmem.c
@@ -93,14 +93,16 @@
void pw_free (/*@out@*/ /*@only@*/struct passwd *pwent)
{
- free (pwent->pw_name);
- if (pwent->pw_passwd) {
- memzero (pwent->pw_passwd, strlen (pwent->pw_passwd));
- free (pwent->pw_passwd);
+ if (pwent != NULL) {
+ free (pwent->pw_name);
+ if (pwent->pw_passwd) {
+ memzero (pwent->pw_passwd, strlen (pwent->pw_passwd));
+ free (pwent->pw_passwd);
+ }
+ free (pwent->pw_gecos);
+ free (pwent->pw_dir);
+ free (pwent->pw_shell);
+ free (pwent);
}
- free (pwent->pw_gecos);
- free (pwent->pw_dir);
- free (pwent->pw_shell);
- free (pwent);
}
diff --git a/lib/shadowmem.c b/lib/shadowmem.c
index 8989598f8..1d047cc04 100644
--- a/lib/shadowmem.c
+++ b/lib/shadowmem.c
@@ -79,11 +79,13 @@
void spw_free (/*@out@*/ /*@only@*/struct spwd *spent)
{
- free (spent->sp_namp);
- if (NULL != spent->sp_pwdp) {
- memzero (spent->sp_pwdp, strlen (spent->sp_pwdp));
- free (spent->sp_pwdp);
+ if (spent != NULL) {
+ free (spent->sp_namp);
+ if (NULL != spent->sp_pwdp) {
+ memzero (spent->sp_pwdp, strlen (spent->sp_pwdp));
+ free (spent->sp_pwdp);
+ }
+ free (spent);
}
- free (spent);
}

View File

@ -0,0 +1,58 @@
From d324c6776b3a1d4ac22bced543f72dc5dd366927 Mon Sep 17 00:00:00 2001
From: Iker Pedrosa <ipedrosa@redhat.com>
Date: Thu, 6 Oct 2022 11:21:18 +0200
Subject: [PATCH] libmisc: minimum id check for system accounts
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The minimum id allocation for system accounts shouldn't be 0 as this is
reserved for root.
Signed-off-by: Tomáš Mráz <tm@t8m.info>
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
Conflict: NA
Reference: https://github.com/shadow-maint/shadow/commit/d324c6776b3a1d4ac22bced543f72dc5dd366927
---
libmisc/find_new_gid.c | 7 +++++++
libmisc/find_new_uid.c | 7 +++++++
2 files changed, 14 insertions(+)
diff --git a/libmisc/find_new_gid.c b/libmisc/find_new_gid.c
index 666b61078..65ab5d013 100644
--- a/libmisc/find_new_gid.c
+++ b/libmisc/find_new_gid.c
@@ -60,6 +60,13 @@ static int get_ranges (bool sys_group, gid_t *min_id, gid_t *max_id,
(unsigned long) *max_id);
return EINVAL;
}
+ /*
+ * Zero is reserved for root and the allocation algorithm does not
+ * work right with it.
+ */
+ if (*min_id == 0) {
+ *min_id = (gid_t) 1;
+ }
} else {
/* Non-system groups */
diff --git a/libmisc/find_new_uid.c b/libmisc/find_new_uid.c
index 322d15ab7..5f7e74b53 100644
--- a/libmisc/find_new_uid.c
+++ b/libmisc/find_new_uid.c
@@ -60,6 +60,13 @@ static int get_ranges (bool sys_user, uid_t *min_id, uid_t *max_id,
(unsigned long) *max_id);
return EINVAL;
}
+ /*
+ * Zero is reserved for root and the allocation algorithm does not
+ * work right with it.
+ */
+ if (*min_id == 0) {
+ *min_id = (uid_t) 1;
+ }
} else {
/* Non-system users */

View File

@ -0,0 +1,45 @@
From 02b200c9aa501ad4e1651c553cea1aaf9e5e0f4f Mon Sep 17 00:00:00 2001
From: Serge Hallyn <serge@hallyn.com>
Date: Sat, 14 Aug 2021 14:24:03 -0500
Subject: [PATCH] man/po/Makefile.in: switch from xml2po to itstool
xml2po is deprecated. We've previously replaced xml2po with
itstool in man/generate_translations.mak, but there was still
an instance of it that only is exercised for 'make dist'.
Update that one. Now 'make dist' succeeds on a ubuntu focal
or newer host where xml2po is not available.
Signed-off-by: Serge Hallyn <serge@hallyn.com>
Conflict: NA
Reference: https://github.com/shadow-maint/shadow/commit/02b200c9aa501ad4e1651c553cea1aaf9e5e0f4f
---
man/po/Makefile.in | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/man/po/Makefile.in b/man/po/Makefile.in
index deaa87058..f194957b4 100644
--- a/man/po/Makefile.in
+++ b/man/po/Makefile.in
@@ -90,9 +90,17 @@ $(DOMAIN).pot-update: $(XMLFILES) $(srcdir)/XMLFILES remove-potcdate.sed
@set -e; tmpdir=`pwd`; \
echo "cd $(top_srcdir)/man"; \
cd $(top_srcdir)/man; \
- echo "xml2po --expand-all-entities -o $$tmpdir/$(DOMAIN).po $(notdir $(XMLFILES))"; \
- xml2po --expand-all-entities -o $$tmpdir/$(DOMAIN).po $(notdir $(XMLFILES)); \
- cd $$tmpdir
+ files=""; \
+ for file in $(notdir $(XMLFILES)); do \
+ if grep -q SHADOW-CONFIG-HERE $$file ; then \
+ sed -e 's/^<!-- SHADOW-CONFIG-HERE -->/<!ENTITY % config SYSTEM "config.xml">%config;/' $$file > $$file.out; \
+ else \
+ sed -e 's/^\(<!DOCTYPE .*docbookx.dtd"\)>/\1 [<!ENTITY % config SYSTEM "config.xml">%config;]>/' $$file > $$file.out; \
+ fi; \
+ files="$$files $$file.out"; \
+ done; \
+ itstool -d -o $$tmpdir/$(DOMAIN).po $$files; \
+ cd $$tmpdir; \
test ! -f $(DOMAIN).po || { \
if test -f $(srcdir)/$(DOMAIN).pot; then \
sed -f remove-potcdate.sed < $(srcdir)/$(DOMAIN).pot > $(DOMAIN).1po && \

View File

@ -0,0 +1,60 @@
From 9df4801e0b65073cc8a9031b22a73532ef7fdc2c Mon Sep 17 00:00:00 2001
From: Vegard Nossum <vegard.nossum@oracle.com>
Date: Fri, 21 Jul 2023 14:55:19 +0200
Subject: [PATCH] newgrp: fix potential string injection
Since newgrp is setuid-root, any write() system calls it does in order
to print error messages will be done as the root user.
Unprivileged users can get newgrp to print essentially arbitrary strings
to any open file in this way by passing those strings as argv[0] when
calling execve(). For example:
$ setpid() { (exec -a $1$'\n:' newgrp '' 2>/proc/sys/kernel/ns_last_pid & wait) >/dev/null; }
$ setpid 31000
$ readlink /proc/self
31001
This is not a vulnerability in newgrp; it is a bug in the Linux kernel.
However, this type of bug is not new [1] and it makes sense to try to
mitigate these types of bugs in userspace where possible.
[1]: https://lwn.net/Articles/476947/
Signed-off-by: Vegard Nossum <vegard.nossum@oracle.com>
Reference: https://github.com/shadow-maint/shadow/commit/9df4801e0b65073cc8a9031b22a73532ef7fdc2c
Conflict: NA
---
src/newgrp.c | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/src/newgrp.c b/src/newgrp.c
index babb28e9..f786a96f 100644
--- a/src/newgrp.c
+++ b/src/newgrp.c
@@ -417,10 +417,17 @@ int main (int argc, char **argv)
* but we do not need to restore the previous process persona and we
* don't need to re-exec anything. -- JWP
*/
- Prog = Basename (argv[0]);
+
+ /*
+ * Ensure that "Prog" is always either "newgrp" or "sg" to avoid
+ * injecting arbitrary strings into our stderr/stdout, as this can
+ * be an exploit vector.
+ */
+ is_newgrp = (strcmp (Basename (argv[0]), "newgrp") == 0);
+ Prog = is_newgrp ? "newgrp" : "sg";
+
shadow_logfd = stderr;
- is_newgrp = (strcmp (Prog, "newgrp") == 0);
- OPENLOG (is_newgrp ? "newgrp" : "sg");
+ OPENLOG (Prog);
argc--;
argv++;
--
2.27.0

View File

@ -0,0 +1,40 @@
From 812f934e77700afedbf5e929b282f29a47b2d9c6 Mon Sep 17 00:00:00 2001
From: Samanta Navarro <ferivoz@riseup.net>
Date: Thu, 18 May 2023 11:56:17 +0000
Subject: [PATCH] process_prefix_flag: Drop privileges
Using --prefix in a setuid binary is quite dangerous. An unprivileged
user could prepare a custom shadow file in home directory. During a data
race the user could exchange directories with links which could lead to
exchange of shadow file in system's /etc directory.
This could be used for local privilege escalation.
Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
---
libmisc/prefix_flag.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/libmisc/prefix_flag.c b/libmisc/prefix_flag.c
index 56243f2e..d7acb9ca 100644
--- a/libmisc/prefix_flag.c
+++ b/libmisc/prefix_flag.c
@@ -85,6 +85,15 @@ extern const char* process_prefix_flag (const char* short_opt, int argc, char **
if (prefix != NULL) {
+ /* Drop privileges */
+ if ( (setregid (getgid (), getgid ()) != 0)
+ || (setreuid (getuid (), getuid ()) != 0)) {
+ fprintf (shadow_logfd,
+ _("%s: failed to drop privileges (%s)\n"),
+ Prog, strerror (errno));
+ exit (EXIT_FAILURE);
+ }
+
if ( prefix[0] == '\0' || !strcmp(prefix, "/"))
return ""; /* if prefix is "/" then we ignore the flag option */
/* should we prevent symbolic link from being used as a prefix? */
--
2.27.0

View File

@ -0,0 +1,125 @@
From 4e1f674c41724dd96ad2c3a0c02ac9f6666697ba Mon Sep 17 00:00:00 2001
From: ed neville <ed@s5h.net>
Date: Mon, 27 Mar 2023 20:23:03 +0100
Subject: [PATCH] run_parts for groupadd and groupdel
run_parts currently exists in useradd and userdel, this commit mirrors
the functionality with groupadd and groupdel
Hook for group{add,del} to include killing processes that have group
membership that would no longer exist to avoid membership ID reuse.
Conflict: NA
Reference: https://github.com/shadow-maint/shadow/commit/4e1f674c41724dd96ad2c3a0c02ac9f6666697ba
---
.../groupdel-pre.d/01-kill_group_procs.sh | 26 +++++++++++++++++++
src/groupadd.c | 11 ++++++++
src/groupdel.c | 11 ++++++++
3 files changed, 48 insertions(+)
create mode 100644 etc/shadow-maint/groupdel-pre.d/01-kill_group_procs.sh
diff --git a/etc/shadow-maint/groupdel-pre.d/01-kill_group_procs.sh b/etc/shadow-maint/groupdel-pre.d/01-kill_group_procs.sh
new file mode 100644
index 000000000..10db52794
--- /dev/null
+++ b/etc/shadow-maint/groupdel-pre.d/01-kill_group_procs.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
+GROUPID=`awk -F: '$1 == "'"${SUBJECT}"'" { print $3 }' /etc/group`
+
+if [ "${GROUPID}" = "" ]; then
+ exit 0
+fi
+
+for status in /proc/*/status; do
+ # either this isn't a process or its already dead since expanding the list
+ [ -f "$status" ] || continue
+
+ tbuf=${status%/status}
+ pid=${tbuf#/proc/}
+ case "$pid" in
+ "$$") continue;;
+ [0-9]*) :;;
+ *) continue
+ esac
+
+ grep -q '^Groups:.*\b'"${GROUPID}"'\b.*' "/proc/$pid/status" || continue
+
+ kill -9 "$pid" || echo "cannot kill $pid" 1>&2
+done
+
diff --git a/src/groupadd.c b/src/groupadd.c
index 311421014..2eda1c680 100644
--- a/src/groupadd.c
+++ b/src/groupadd.c
@@ -34,6 +34,7 @@
#ifdef SHADOWGRP
#include "sgroupio.h"
#endif
+#include "run_part.h"
/*
* exit status values
@@ -603,6 +604,11 @@ int main (int argc, char **argv)
check_perms ();
+ if (run_parts ("/etc/shadow-maint/groupadd-pre.d", group_name,
+ "groupadd")) {
+ exit(1);
+ }
+
#ifdef SHADOWGRP
is_shadow_grp = sgr_file_present ();
#endif
@@ -621,6 +627,11 @@ int main (int argc, char **argv)
grp_update ();
close_files ();
+ if (run_parts ("/etc/shadow-maint/groupadd-post.d", group_name,
+ "groupadd")) {
+ exit(1);
+ }
+
nscd_flush_cache ("group");
sssd_flush_cache (SSSD_DB_GROUP);
diff --git a/src/groupdel.c b/src/groupdel.c
index fdccf5e15..bae4367ba 100644
--- a/src/groupdel.c
+++ b/src/groupdel.c
@@ -32,6 +32,7 @@
#ifdef SHADOWGRP
#include "sgroupio.h"
#endif
+#include "run_part.h"
/*
* Global variables
*/
@@ -461,6 +462,11 @@ int main (int argc, char **argv)
group_busy (group_id);
}
+ if (run_parts ("/etc/shadow-maint/groupdel-pre.d", group_name,
+ "groupdel")) {
+ exit(1);
+ }
+
/*
* Do the hard stuff - open the files, delete the group entries,
* then close and update the files.
@@ -471,6 +477,11 @@ int main (int argc, char **argv)
close_files ();
+ if (run_parts ("/etc/shadow-maint/groupdel-post.d", group_name,
+ "groupdel")) {
+ exit(1);
+ }
+
nscd_flush_cache ("group");
sssd_flush_cache (SSSD_DB_GROUP);

View File

@ -0,0 +1,54 @@
From dcca8653a54b5a03b0234238dbc6388f6b59adc3 Mon Sep 17 00:00:00 2001
From: ed neville <ed@s5h.net>
Date: Fri, 17 Dec 2021 14:29:48 +0000
Subject: [PATCH] script to kill subjects processes from userdel
Closes #404
Closes #317
Signed-off-by: ed neville <ed@s5h.net>
Conflict: NA
Reference: https://github.com/shadow-maint/shadow/commit/dcca8653a54b5a03b0234238dbc6388f6b59adc3
---
.../userdel-pre.d/01-kill_user_procs.sh | 28 +++++++++++++++++++
1 file changed, 28 insertions(+)
create mode 100755 etc/shadow-maint/userdel-pre.d/01-kill_user_procs.sh
diff --git a/etc/shadow-maint/userdel-pre.d/01-kill_user_procs.sh b/etc/shadow-maint/userdel-pre.d/01-kill_user_procs.sh
new file mode 100755
index 00000000..ca481b1b
--- /dev/null
+++ b/etc/shadow-maint/userdel-pre.d/01-kill_user_procs.sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+
+PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
+
+# Check user exists, and if so, send sigkill to processes that the user owns
+
+RUNNING=`ps -eo user | grep -Fx "$SUBJECT" | wc -l`
+
+# if the user does not exist, RUNNING will be 0
+
+if [ "${RUNNING}x" = "0x" ]; then
+ exit 0
+fi
+
+ls -1 /proc | while IFS= read -r PROC; do
+ echo "$PROC" | grep -E '^[0-9]+$' >/dev/null
+ if [ $? -ne 0 ]; then
+ continue
+ fi
+ if [ -d "/proc/${PROC}" ]; then
+ USR=`stat -c "%U" /proc/${PROC}`
+ if [ "${USR}" = "${SUBJECT}" ]; then
+ echo "Killing ${SUBJECT} owned ${PROC}"
+ kill -9 "${PROC}"
+ fi
+ fi
+done
+
--
2.27.0

View File

@ -0,0 +1,56 @@
From 7bced397c9fd66965753e5fc0fd3dfa535ca1c9b Mon Sep 17 00:00:00 2001
From: xiongshenglan <xiongshenglan@huawei.com>
Date: Wed, 19 Jul 2023 15:13:06 +0800
Subject: [PATCH] shadow userdel: add the adaptation to the busybox ps in
01-kill_user_procs.sh
In some embedded systems, users only use the ps
provided by the busybox. But the ps provided by
the busybox does not support the -eo option by
default. As a result, an error is reported when
the userdel is used. So add a judgment on ps.
If there is no ps -eo, traverse the process directly.
The error information is as follows:
# userdel xsl
ps: invalid option -- 'e'
Signed-off-by: xiongshenglan <xiongshenglan@huawei.com>
Reference: https://github.com/shadow-maint/shadow/commit/7bced397c9fd66965753e5fc0fd3dfa535ca1c9b
Conflict: NA
---
.../userdel-pre.d/01-kill_user_procs.sh | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/etc/shadow-maint/userdel-pre.d/01-kill_user_procs.sh b/etc/shadow-maint/userdel-pre.d/01-kill_user_procs.sh
index ca481b1b..d2d7ef26 100755
--- a/etc/shadow-maint/userdel-pre.d/01-kill_user_procs.sh
+++ b/etc/shadow-maint/userdel-pre.d/01-kill_user_procs.sh
@@ -4,14 +4,17 @@ PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
# Check user exists, and if so, send sigkill to processes that the user owns
-RUNNING=`ps -eo user | grep -Fx "$SUBJECT" | wc -l`
-
-# if the user does not exist, RUNNING will be 0
-
-if [ "${RUNNING}x" = "0x" ]; then
- exit 0
+ps -eo user >/dev/null 2>&1
+if [ $? -eq 0 ]; then
+ RUNNING=`ps -eo user | grep -Fx "$SUBJECT" | wc -l`
+ # if the user does not exist, RUNNING will be 0
+ if [ "${RUNNING}x" = "0x" ]; then
+ exit 0
+ fi
fi
+# If there is no ps -eo, traverse the process directly.
+
ls -1 /proc | while IFS= read -r PROC; do
echo "$PROC" | grep -E '^[0-9]+$' >/dev/null
if [ $? -ne 0 ]; then
--
2.27.0

View File

@ -0,0 +1,32 @@
From 2d188a9987789f019dae2d46c50578a474ab2bdd Mon Sep 17 00:00:00 2001
From: Tobias Stoeckmann <tobias@stoeckmann.org>
Date: Wed, 20 Dec 2023 20:48:54 +0100
Subject: [PATCH] src/passwd.c: Add overflow check
Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
Link: <https://github.com/shadow-maint/shadow/pull/876>
Co-developed-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Reference: https://github.com/shadow-maint/shadow/commit/2d188a9987789f019dae2d46c50578a474ab2bdd
Conflict: NA
---
src/passwd.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/passwd.c b/src/passwd.c
index a24e62dfd..f494a9257 100644
--- a/src/passwd.c
+++ b/src/passwd.c
@@ -387,8 +387,9 @@ static void check_password (const struct passwd *pw, const struct spwd *sp)
long now, ok;
now = time(NULL) / DAY;
ok = sp->sp_lstchg;
- if (sp->sp_min > 0) {
- ok += sp->sp_min;
+ if ( (sp->sp_min > 0)
+ && __builtin_add_overflow(ok, sp->sp_min, &ok)) {
+ ok = LONG_MAX;
}
if (now < ok) {

View File

@ -0,0 +1,61 @@
From 3b5ba41d3e9dfc3bf058f0f31529c08201265241 Mon Sep 17 00:00:00 2001
From: Tobias Stoeckmann <tobias@stoeckmann.org>
Date: Thu, 14 Dec 2023 11:54:00 +0100
Subject: [PATCH] src/passwd.c: Switch to day precision
The size of time_t varies across systems, but since data type long is
more than enough to calculate with days (precision of shadow file),
use it instead.
Just in case a shadow file contains huge values, check for a possible
signed integer overflow.
Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
Link: <https://github.com/shadow-maint/shadow/pull/876>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Reference: https://github.com/shadow-maint/shadow/commit/3b5ba41d3e9dfc3bf058f0f31529c08201265241
Conflict: src/chpasswd.c
---
src/passwd.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/src/passwd.c b/src/passwd.c
index 336bbc9..d79767a 100644
--- a/src/passwd.c
+++ b/src/passwd.c
@@ -390,7 +390,6 @@ static int new_password (const struct passwd *pw)
*/
static void check_password (const struct passwd *pw, const struct spwd *sp)
{
- time_t now;
int exp_status;
exp_status = isexpired (pw, sp);
@@ -410,8 +409,6 @@ static void check_password (const struct passwd *pw, const struct spwd *sp)
return;
}
- (void) time (&now);
-
/*
* Expired accounts cannot be changed ever. Passwords which are
* locked may not be changed. Passwords where min > max may not be
@@ -434,10 +431,11 @@ static void check_password (const struct passwd *pw, const struct spwd *sp)
* Passwords may only be changed after sp_min time is up.
*/
if (sp->sp_lstchg > 0) {
- time_t ok;
- ok = (time_t) sp->sp_lstchg * SCALE;
+ long now, ok;
+ now = time(NULL) / DAY;
+ ok = sp->sp_lstchg;
if (sp->sp_min > 0) {
- ok += (time_t) sp->sp_min * SCALE;
+ ok += sp->sp_min;
}
if (now < ok) {
--
2.33.0

View File

@ -0,0 +1,60 @@
From 23634d8de7d01ed65bd70e316d4da4fe4d9b370d Mon Sep 17 00:00:00 2001
From: genBTC <genBTC@gmx.com>
Date: Tue, 23 Aug 2022 10:25:51 -0400
Subject: [PATCH] useradd: check MLS enablement before setting serange
Resolves: https://github.com/shadow-maint/shadow/issues/552
Conflict: NA
Reference: https://github.com/shadow-maint/shadow/commit/23634d8de7d01ed65bd70e316d4da4fe4d9b370d
---
lib/semanage.c | 29 ++++++++++++++++-------------
1 file changed, 16 insertions(+), 13 deletions(-)
diff --git a/lib/semanage.c b/lib/semanage.c
index 54f996238..082a6e8ee 100644
--- a/lib/semanage.c
+++ b/lib/semanage.c
@@ -122,12 +122,14 @@ static int semanage_user_mod (semanage_handle_t *handle,
goto done;
}
- ret = semanage_seuser_set_mlsrange (handle, seuser, DEFAULT_SERANGE);
- if (ret != 0) {
- fprintf (shadow_logfd,
- _("Could not set serange for %s\n"), login_name);
- ret = 1;
- goto done;
+ if (semanage_mls_enabled(handle)) {
+ ret = semanage_seuser_set_mlsrange (handle, seuser, DEFAULT_SERANGE);
+ if (ret != 0) {
+ fprintf (shadow_logfd,
+ _("Could not set serange for %s\n"), login_name);
+ ret = 1;
+ goto done;
+ }
}
ret = semanage_seuser_set_sename (handle, seuser, seuser_name);
@@ -179,13 +181,14 @@ static int semanage_user_add (semanage_handle_t *handle,
goto done;
}
- ret = semanage_seuser_set_mlsrange (handle, seuser, DEFAULT_SERANGE);
- if (ret != 0) {
- fprintf (shadow_logfd,
- _("Could not set serange for %s\n"),
- login_name);
- ret = 1;
- goto done;
+ if (semanage_mls_enabled(handle)) {
+ ret = semanage_seuser_set_mlsrange (handle, seuser, DEFAULT_SERANGE);
+ if (ret != 0) {
+ fprintf (shadow_logfd,
+ _("Could not set serange for %s\n"), login_name);
+ ret = 1;
+ goto done;
+ }
}
ret = semanage_seuser_set_sename (handle, seuser, seuser_name);

View File

@ -0,0 +1,39 @@
From e0524e813a3bae2891b33a66f35876841c11cee7 Mon Sep 17 00:00:00 2001
From: Iker Pedrosa <ipedrosa@redhat.com>
Date: Mon, 24 Oct 2022 10:46:36 +0200
Subject: [PATCH] useradd: check if subid range exists for user
Check if a user already has a subid range before assigning one.
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2012929
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
Conflict: NA
Reference: https://github.com/shadow-maint/shadow/commit/f6f8bcd2a57c06983296485cc028ebdf467ebfd7
---
src/useradd.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/useradd.c b/src/useradd.c
index 7ea0a9c4d..e784d6029 100644
--- a/src/useradd.c
+++ b/src/useradd.c
@@ -2188,14 +2188,14 @@ static void usr_update (unsigned long subuid_count, unsigned long subgid_count)
fail_exit (E_PW_UPDATE);
}
#ifdef ENABLE_SUBIDS
- if (is_sub_uid &&
+ if (is_sub_uid && !local_sub_uid_assigned(user_name) &&
(sub_uid_add(user_name, sub_uid_start, subuid_count) == 0)) {
fprintf (stderr,
_("%s: failed to prepare the new %s entry\n"),
Prog, sub_uid_dbname ());
fail_exit (E_SUB_UID_UPDATE);
}
- if (is_sub_gid &&
+ if (is_sub_gid && !local_sub_gid_assigned(user_name) &&
(sub_gid_add(user_name, sub_gid_start, subgid_count) == 0)) {
fprintf (stderr,
_("%s: failed to prepare the new %s entry\n"),

View File

@ -0,0 +1,39 @@
From 7a2b302e68a4f3e324b851c7361e40aa20a86a64 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Thu, 2 Mar 2023 16:18:45 +0100
Subject: [PATCH] usermod: fix off-by-one issues
Allocate enough memory for the strings, two slashes and the NUL
terminator.
Reported-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
---
src/usermod.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/usermod.c b/src/usermod.c
index 77d4ef49..db5d37a4 100644
--- a/src/usermod.c
+++ b/src/usermod.c
@@ -2048,7 +2048,7 @@ static void move_mailbox (void)
if (NULL == maildir) {
return;
}
- len = strlen (prefix) + strlen (maildir) + strlen (user_name) + 2;
+ len = strlen (prefix) + strlen (maildir) + strlen (user_name) + 3;
mailfile = alloca (len);
/*
@@ -2103,7 +2103,7 @@ static void move_mailbox (void)
(void) close (fd);
if (lflg) {
- len = strlen (prefix) + strlen (maildir) + strlen (user_newname) + 2;
+ len = strlen (prefix) + strlen (maildir) + strlen (user_newname) + 3;
newmailfile = alloca(len);
if (prefix[0]) {
(void) snprintf (newmailfile, len, "%s/%s/%s",
--
2.27.0

26
chpasswd.sh Normal file
View File

@ -0,0 +1,26 @@
# chpasswd(8) completion -*- shell-script -*-
_chpasswd()
{
local cur prev words cword split
_init_completion -s || return
case $prev in
-c|--crypt)
COMPREPLY=( $( compgen -W 'DES MD5 NONE SHA256 SHA512 SM3' \
-- "$cur" ) )
return
;;
-s|--sha-rounds)
return
;;
esac
$split && return
COMPREPLY=( $( compgen -W '$( _parse_help "$1" )' -- "$cur" ) )
[[ $COMPREPLY == *= ]] && compopt -o nospace
} &&
complete -F _chpasswd chpasswd
# ex: filetype=sh

View File

@ -0,0 +1,133 @@
From 280a8474ad87f44f9620eeac75cbf8a34b5edc2f Mon Sep 17 00:00:00 2001
From: xiongshenglan <xiongshenglan@huawei.com>
Date: Thu, 27 Jul 2023 09:30:16 +0800
Subject: [PATCH] shadow: Remove encrypted passwd for
useradd-groupadd-groupmod-usermod
Remove encrypted passwd for useradd/groupadd/groupmod/usermod
In groupadd/useradd, p parameter does not meet password complexity checks. Do
not satisfy security requirements.
Signed-off-by: xiongshenglan <xiongshenglan@huawei.com>
---
src/groupadd.c | 4 ++++
src/groupmod.c | 4 ++++
src/useradd.c | 4 ++++
src/usermod.c | 4 ++++
4 files changed, 16 insertions(+)
diff --git a/src/groupadd.c b/src/groupadd.c
index d7f68b1..9b7a521 100644
--- a/src/groupadd.c
+++ b/src/groupadd.c
@@ -125,7 +125,9 @@ static /*@noreturn@*/void usage (int status)
(void) fputs (_(" -K, --key KEY=VALUE override /etc/login.defs defaults\n"), usageout);
(void) fputs (_(" -o, --non-unique allow to create groups with duplicate\n"
" (non-unique) GID\n"), usageout);
+#ifndef CONFIG_SHADOW_REMOVE_POPTION
(void) fputs (_(" -p, --password PASSWORD use this encrypted password for the new group\n"), usageout);
+#endif
(void) fputs (_(" -r, --system create a system account\n"), usageout);
(void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), usageout);
(void) fputs (_(" -P, --prefix PREFIX_DI directory prefix\n"), usageout);
@@ -459,10 +461,12 @@ static void process_flags (int argc, char **argv)
case 'o':
oflg = true;
break;
+#ifndef CONFIG_SHADOW_REMOVE_POPTION
case 'p':
pflg = true;
group_passwd = optarg;
break;
+#endif
case 'r':
rflg = true;
break;
diff --git a/src/groupmod.c b/src/groupmod.c
index acd6f35..f9dcabd 100644
--- a/src/groupmod.c
+++ b/src/groupmod.c
@@ -139,8 +139,10 @@ static void usage (int status)
(void) fputs (_(" -h, --help display this help message and exit\n"), usageout);
(void) fputs (_(" -n, --new-name NEW_GROUP change the name to NEW_GROUP\n"), usageout);
(void) fputs (_(" -o, --non-unique allow to use a duplicate (non-unique) GID\n"), usageout);
+#ifndef CONFIG_SHADOW_REMOVE_POPTION
(void) fputs (_(" -p, --password PASSWORD change the password to this (encrypted)\n"
" PASSWORD\n"), usageout);
+#endif
(void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), usageout);
(void) fputs (_(" -P, --prefix PREFIX_DIR prefix directory where are located the /etc/* files\n"), usageout);
(void) fputs (_(" -U, --users USERS list of user members of this group\n"), usageout);
@@ -449,10 +451,12 @@ static void process_flags (int argc, char **argv)
case 'o':
oflg = true;
break;
+#ifndef CONFIG_SHADOW_REMOVE_POPTION
case 'p':
group_passwd = optarg;
pflg = true;
break;
+#endif
case 'R': /* no-op, handled in process_root_flag () */
break;
case 'P': /* no-op, handled in process_prefix_flag () */
diff --git a/src/useradd.c b/src/useradd.c
index 89abd5e..e5ba3dd 100644
--- a/src/useradd.c
+++ b/src/useradd.c
@@ -907,7 +907,9 @@ static void usage (int status)
" the user\n"), usageout);
(void) fputs (_(" -o, --non-unique allow to create users with duplicate\n"
" (non-unique) UID\n"), usageout);
+#ifndef CONFIG_SHADOW_REMOVE_POPTION
(void) fputs (_(" -p, --password PASSWORD encrypted password of the new account\n"), usageout);
+#endif
(void) fputs (_(" -r, --system create a system account\n"), usageout);
(void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), usageout);
(void) fputs (_(" -P, --prefix PREFIX_DIR prefix directory where are located the /etc/* files\n"), usageout);
@@ -1366,6 +1368,7 @@ static void process_flags (int argc, char **argv)
case 'o':
oflg = true;
break;
+#ifndef CONFIG_SHADOW_REMOVE_POPTION
case 'p': /* set encrypted password */
if (!VALID (optarg)) {
fprintf (stderr,
@@ -1375,6 +1378,7 @@ static void process_flags (int argc, char **argv)
}
user_pass = optarg;
break;
+#endif
case 'r':
rflg = true;
break;
diff --git a/src/usermod.c b/src/usermod.c
index ca8db92..509a50b 100644
--- a/src/usermod.c
+++ b/src/usermod.c
@@ -435,7 +435,9 @@ static /*@noreturn@*/void usage (int status)
(void) fputs (_(" -m, --move-home move contents of the home directory to the\n"
" new location (use only with -d)\n"), usageout);
(void) fputs (_(" -o, --non-unique allow using duplicate (non-unique) UID\n"), usageout);
+#ifndef CONFIG_SHADOW_REMOVE_POPTION
(void) fputs (_(" -p, --password PASSWORD use encrypted password for the new password\n"), usageout);
+#endif
(void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), usageout);
(void) fputs (_(" -P, --prefix PREFIX_DIR prefix directory where are located the /etc/* files\n"), usageout);
(void) fputs (_(" -s, --shell SHELL new login shell for the user account\n"), usageout);
@@ -1152,10 +1154,12 @@ static void process_flags (int argc, char **argv)
case 'o':
oflg = true;
break;
+#ifndef CONFIG_SHADOW_REMOVE_POPTION
case 'p':
user_pass = optarg;
pflg = true;
break;
+#endif
case 'R': /* no-op, handled in process_root_flag () */
break;
case 'P': /* no-op, handled in process_prefix_flag () */
--
2.12.3

View File

@ -1,6 +1,6 @@
Name: shadow
Version: 4.9
Release: 10
Release: 15
Epoch: 2
License: BSD and GPLv2+
Summary: Tools for managing accounts and shadow password files
@ -12,6 +12,7 @@ Source4: shadow-bsd.txt
Source5: https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
Source6: chpasswd
Source7: newusers
Source8: chpasswd.sh
%global includesubiddir %{_includedir}/shadow
@ -37,27 +38,64 @@ Patch17: newgrp-fix-segmentation-fault.patch
Patch18: groupdel-fix-SIGSEGV-when-passwd-does-not-exist.patch
Patch19: shadow-add-sm3-crypt-support.patch
Patch20: backport-useradd-modify-check-ID-range-for-system-users.patch
Patch21: backport-Add-header-guards.patch
Patch22: backport-Change-to-strncat.patch
Patch23: backport-Do-not-return-garbage-in-run_parts.patch
Patch24: backport-Handle-ERANGE-error-correctly.patch
Patch25: backport-Initialize-local-variables.patch
Patch26: backport-Remove-commented-out-code-and-FIXMEs.patch
Patch27: backport-Remove-redeclared-variable.patch
Patch28: backport-libmisc-add-check-fopen-return-value-in-read_random_.patch
Patch29: backport-passwd-erase-password-copy-on-all-error-branches.patch
Patch30: backport-chpasswd-add-get_salt-for-generating-salt-value.patch
Patch31: backport-chpasswd-fix-function-problem-with-R-parameter.patch
Patch32: backport-Fix-off-by-one-mistakes.patch
Patch33: backport-Fix-typos-in-length-calculations.patch
Patch34: backport-Correctly-handle-illegal-system-file-in-tz.patch
Patch35: backport-Explicitly-override-only-newlines.patch
Patch36: backport-Prevent-out-of-boundary-access.patch
Patch37: backport-Added-control-character-check.patch
Patch38: backport-Overhaul-valid_field.patch
Patch39: backport-Read-whole-line-in-yes_or_no.patch
Patch40: backport-commonio-free-removed-database-entries.patch
Patch41: backport-semanage-disconnect-to-free-libsemanage-internals.patch
Patch21: backport-man-po-Makefile.in-switch-from-xml2po-to-itstool.patch
Patch22: backport-Only-free-sgent-if-it-was-initialized.patch
Patch23: backport-Fix-parentheses-in-configure.ac.patch
Patch24: backport-Added-documentation-around-CREATE_MAIL_SPOOL.patch
Patch26: backport-Handle-malformed-lines-in-hushlogins-file.patch
Patch27: backport-Improve-child-error-handling.patch
Patch28: backport-lib-check-NULL-before-freeing-passwd-data.patch
Patch29: backport-CVE-2013-4235.patch
Patch30: backport-Add-header-guards.patch
Patch31: backport-Change-to-strncat.patch
Patch32: backport-Handle-ERANGE-error-correctly.patch
Patch33: backport-Do-not-return-garbage-in-run_parts.patch
Patch34: backport-Initialize-local-variables.patch
Patch35: backport-libmisc-add-check-fopen-return-value-in-read_random_.patch
Patch36: backport-passwd-erase-password-copy-on-all-error-branches.patch
Patch37: backport-Remove-commented-out-code-and-FIXMEs.patch
Patch38: backport-Remove-redeclared-variable.patch
Patch39: backport-chpasswd-add-get_salt-for-generating-salt-value.patch
Patch40: backport-chpasswd-fix-function-problem-with-R-parameter.patch
Patch41: backport-script-to-kill-subjects-processes-from-userdel.patch
Patch42: backport-Avoid-races-in-chown_tree.patch
Patch43: backport-Avoid-races-in-remove_tree.patch
Patch44: backport-Require-symlink-support.patch
Patch45: backport-Fail-if-regular-file-pre-exists-in-copy_tree.patch
Patch46: backport-More-robust-file-content-copy-in-copy_tree.patch
Patch47: backport-Address-minor-compiler-warnings.patch
Patch48: backport-Avoid-races-in-copy_tree.patch
Patch49: backport-useradd-check-MLS-enablement-before-setting-serange.patch
Patch50: backport-libmisc-minimum-id-check-for-system-accounts.patch
Patch51: backort-useradd-Fix-buffer-overflow-when-using-a-prefix.patch
Patch52: backport-useradd-check-if-subid-range-exists-for-user.patch
Patch53: backport-Fix-off-by-one-mistakes.patch
Patch54: backport-Fix-typos-in-length-calculations.patch
Patch55: backport-Correctly-handle-illegal-system-file-in-tz.patch
Patch56: backport-Explicitly-override-only-newlines.patch
Patch57: backport-Prevent-out-of-boundary-access.patch
Patch58: backport-Added-control-character-check.patch
Patch59: backport-Overhaul-valid_field.patch
Patch60: backport-Read-whole-line-in-yes_or_no.patch
Patch61: backport-run_parts-for-groupadd-and-groupdel.patch
Patch62: backport-commonio-free-removed-database-entries.patch
Patch63: backport-semanage-disconnect-to-free-libsemanage-internals.patch
Patch64: backport-process_prefix_flag-Drop-privileges.patch
Patch65: backport-chsh-Verify-that-login-shell-path-is-absolute.patch
Patch66: backport-Plug-econf-memory-leaks.patch
Patch67: backport-def_load-avoid-NULL-deref.patch
Patch68: backport-Check-if-crypt_method-null-before-dereferencing.patch
Patch69: backport-usermod-fix-off-by-one-issues.patch
Patch70: backport-gpasswd-1-Fix-password-leak.patch
Patch71: backport-chgpasswd-fix-segfault-in-command-line-options.patch
Patch72: backport-chpasswd-add-IS_CRYPT_METHOD.patch
Patch73: backport-Fix-yescrypt-support.patch
Patch74: backport-newgrp-fix-potential-string-injection.patch
Patch75: shadow-Remove-encrypted-passwd-for-useradd-gr.patch
Patch76: backport-shadow-userdel-add-the-adaptation-to-the-busybox-ps-.patch
Patch77: backport-lib-btrfs-avoid-NULL-dereference.patch
Patch78: backport-src-passwd.c-Switch-to-day-precision.patch
Patch79: backport-src-passwd-add-overflow-check.patch
BuildRequires: gcc, libselinux-devel, audit-libs-devel, libsemanage-devel
BuildRequires: libacl-devel, libattr-devel
@ -120,6 +158,8 @@ install -p -c -m 0644 %{SOURCE3} $RPM_BUILD_ROOT/%{_sysconfdir}/login.defs
install -p -c -m 0600 %{SOURCE2} $RPM_BUILD_ROOT/%{_sysconfdir}/default/useradd
install -p -c -m 0644 %{SOURCE6} $RPM_BUILD_ROOT/%{_sysconfdir}/pam.d/chpasswd
install -p -c -m 0644 %{SOURCE7} $RPM_BUILD_ROOT/%{_sysconfdir}/pam.d/newusers
mkdir -p -m755 $RPM_BUILD_ROOT%{_sysconfdir}/bash_completion.d
install -p -c -m 0644 %{SOURCE8} $RPM_BUILD_ROOT/%{_sysconfdir}/bash_completion.d/chpasswd.sh
ln -s useradd $RPM_BUILD_ROOT%{_sbindir}/adduser
ln -s useradd.8 $RPM_BUILD_ROOT/%{_mandir}/man8/adduser.8
@ -214,6 +254,7 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.la
%{_sysconfdir}/pam.d/chpasswd
%{_sysconfdir}/pam.d/groupmems
%{_sysconfdir}/pam.d/newusers
%{_sysconfdir}/bash_completion.d/chpasswd.sh
%files subid-devel
%{_libdir}/libsubid.so.*
@ -224,6 +265,21 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.la
%{_mandir}/*/*
%changelog
* Sun Feb 4 2024 zhengxiaoxiao <zhengxiaoxiao2@huawei.com> - 2:4.9-15
- backport some patches
* Thu Nov 9 2023 wangqingsan <wangqingsan@huawei.com> - 2:4.9-14
- backport some patches
* Wed Sep 20 2023 wangyunjia <yunjia.wang@huawei.com> - 2:4.9-13
- backport some patches
* Tue Aug 22 2023 wangyunjia <yunjia.wang@huawei.com> - 2:4.9-12
- backport patches from upstream
* Fri Aug 15 2023 xiongshenglan<xiongshenglan@huawei.com> - 2:4.9-11
- Remove encrypted passwd for useradd-groupadd-groupmod-usermod
* Mon Jun 19 2023 wangyunjia <yunjia.wang@huawei.com> - 2:4.9-10
- backport patches from upstream