summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlvar Penning <post@0x21.biz>2022-05-26 12:20:30 +0200
committerAlvar Penning <post@0x21.biz>2022-05-26 12:20:30 +0200
commitf1b847e1329b552d2deb9febd0461d3350501165 (patch)
treeb3c71ae8f58c1fdd95b7702bb3fa10981a286288
parentMerge pull request #174427 from wamserma/backport-173474-to-release-21.11 (diff)
downloadnixpkgs-f1b847e1329b552d2deb9febd0461d3350501165.tar.gz
logrotate: fix CVE-2022-1348
-rw-r--r--pkgs/tools/system/logrotate/default.nix8
-rw-r--r--pkgs/tools/system/logrotate/fix-cve-2022-1348.diff69
2 files changed, 77 insertions, 0 deletions
diff --git a/pkgs/tools/system/logrotate/default.nix b/pkgs/tools/system/logrotate/default.nix
index 72e6f5ec71be..4ba13b72bede 100644
--- a/pkgs/tools/system/logrotate/default.nix
+++ b/pkgs/tools/system/logrotate/default.nix
@@ -14,6 +14,14 @@ stdenv.mkDerivation rec {
sha256 = "sha256-OJOV++rtN9ry+l0c0eanpu/Pwu8cOHfyEaDWp3FZjkw=";
};
+ patches = [
+ # Fix CVE-2022-1348 by backporting two upstream commits
+ # - 1f76a381e2caa0603ae3dbc51ed0f1aa0d6658b9 and
+ # - addbd293242b0b78aa54f054e6c1d249451f137d
+ # in a custom patch, as cherry-picking directly failed.
+ ./fix-cve-2022-1348.diff
+ ];
+
# Logrotate wants to access the 'mail' program; to be done.
configureFlags = [
"--with-compress-command=${gzip}/bin/gzip"
diff --git a/pkgs/tools/system/logrotate/fix-cve-2022-1348.diff b/pkgs/tools/system/logrotate/fix-cve-2022-1348.diff
new file mode 100644
index 000000000000..14b65cdaa33a
--- /dev/null
+++ b/pkgs/tools/system/logrotate/fix-cve-2022-1348.diff
@@ -0,0 +1,69 @@
+diff --git a/logrotate.c b/logrotate.c
+index d7a1c19..45b985a 100644
+--- a/logrotate.c
++++ b/logrotate.c
+@@ -2514,6 +2514,7 @@ static int writeState(const char *stateFilename)
+ struct tm now;
+ time_t now_time, last_time;
+ char *prevCtx;
++ int force_mode = 0;
+
+ localtime_r(&nowSecs, &now);
+
+@@ -2581,7 +2582,13 @@ static int writeState(const char *stateFilename)
+
+ close(fdcurr);
+
+- fdsave = createOutputFile(tmpFilename, O_RDWR | O_CREAT | O_TRUNC, &sb, prev_acl, 0);
++ if (sb.st_mode & (mode_t)S_IROTH) {
++ /* drop world-readable flag to prevent others from locking */
++ sb.st_mode &= ~(mode_t)S_IROTH;
++ force_mode = 1;
++ }
++
++ fdsave = createOutputFile(tmpFilename, O_RDWR | O_CREAT | O_TRUNC, &sb, prev_acl, force_mode);
+ #ifdef WITH_ACL
+ if (prev_acl) {
+ acl_free(prev_acl);
+@@ -2915,14 +2922,16 @@ static int readState(const char *stateFilename)
+ static int lockState(const char *stateFilename, int skip_state_lock)
+ {
+ int lockFd = open(stateFilename, O_RDWR | O_CLOEXEC);
++ struct stat sb;
++
+ if (lockFd == -1) {
+ if (errno == ENOENT) {
+ message(MESS_DEBUG, "Creating stub state file: %s\n",
+ stateFilename);
+
+- /* create a stub state file with mode 0644 */
++ /* create a stub state file with mode 0640 */
+ lockFd = open(stateFilename, O_CREAT | O_EXCL | O_WRONLY,
+- S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
++ S_IWUSR | S_IRUSR | S_IRGRP);
+ if (lockFd == -1) {
+ message(MESS_ERROR, "error creating stub state file %s: %s\n",
+ stateFilename, strerror(errno));
+@@ -2942,6 +2951,22 @@ static int lockState(const char *stateFilename, int skip_state_lock)
+ return 0;
+ }
+
++ if (fstat(lockFd, &sb) == -1) {
++ message(MESS_ERROR, "error stat()ing state file %s: %s\n",
++ stateFilename, strerror(errno));
++ close(lockFd);
++ return 1;
++ }
++
++ if (sb.st_mode & S_IROTH) {
++ message(MESS_ERROR, "state file %s is world-readable and thus can"
++ " be locked from other unprivileged users."
++ " Skipping lock acquisition...\n",
++ stateFilename);
++ close(lockFd);
++ return 0;
++ }
++
+ if (flock(lockFd, LOCK_EX | LOCK_NB) == -1) {
+ if (errno == EWOULDBLOCK) {
+ message(MESS_ERROR, "state file %s is already locked\n"