···66Accepted arguments are:
7788- `name`
99- The name of the environment, and the wrapper executable if `pname` is unset.
99+ The name of the environment.
1010- `pname`
1111- The pname of the environment and the wrapper executable.
1111+ The pname of the environment.
1212- `version`
1313 The version of the environment.
1414+- `executableName`
1515+ The name of the wrapper executable. Defaults to `pname` if set, or `name` otherwise.
1416- `targetPkgs`
1517 Packages to be installed for the main host's architecture (i.e. x86_64 on x86_64 installations). Along with libraries binaries are also installed.
1618- `multiPkgs`
···8484- Ensure that the introduced options are correct.
8585 - Type should be appropriate (string related types differs in their merging capabilities, `loaOf` and `string` types are deprecated).
8686 - Description, default and example should be provided.
8787+ - Defaults may only be omitted if both:
8888+ 1. The user is required to set the default in order to properly use the service.
8989+ 2. The lack of a default does not break evaluation when the module is not enabled.
8790- Ensure that module `meta` field is present
8891 - Maintainers should be declared in `meta.maintainers`.
8992 - Module documentation should be declared with `meta.doc`.
···11+From 33385aefe4773e7a3982d41995681eb079c92d12 Mon Sep 17 00:00:00 2001
22+From: Andrew Tridgell <andrew@tridgell.net>
33+Date: Sat, 23 Nov 2024 12:26:10 +1100
44+Subject: [PATCH 2/4] added secure_relative_open()
55+66+this is an open that enforces no symlink following for all path
77+components in a relative path
88+---
99+ syscall.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1010+ 1 file changed, 74 insertions(+)
1111+1212+diff --git a/syscall.c b/syscall.c
1313+index d92074aa..a4b7f542 100644
1414+--- a/syscall.c
1515++++ b/syscall.c
1616+@@ -33,6 +33,8 @@
1717+ #include <sys/syscall.h>
1818+ #endif
1919+2020++#include "ifuncs.h"
2121++
2222+ extern int dry_run;
2323+ extern int am_root;
2424+ extern int am_sender;
2525+@@ -712,3 +714,75 @@ int do_open_nofollow(const char *pathname, int flags)
2626+2727+ return fd;
2828+ }
2929++
3030++/*
3131++ open a file relative to a base directory. The basedir can be NULL,
3232++ in which case the current working directory is used. The relpath
3333++ must be a relative path, and the relpath must not contain any
3434++ elements in the path which follow symlinks (ie. like O_NOFOLLOW, but
3535++ applies to all path components, not just the last component)
3636++*/
3737++int secure_relative_open(const char *basedir, const char *relpath, int flags, mode_t mode)
3838++{
3939++ if (!relpath || relpath[0] == '/') {
4040++ // must be a relative path
4141++ errno = EINVAL;
4242++ return -1;
4343++ }
4444++
4545++#if !defined(O_NOFOLLOW) || !defined(O_DIRECTORY)
4646++ // really old system, all we can do is live with the risks
4747++ if (!basedir) {
4848++ return open(relpath, flags, mode);
4949++ }
5050++ char fullpath[MAXPATHLEN];
5151++ pathjoin(fullpath, sizeof fullpath, basedir, relpath);
5252++ return open(fullpath, flags, mode);
5353++#else
5454++ int dirfd = AT_FDCWD;
5555++ if (basedir != NULL) {
5656++ dirfd = openat(AT_FDCWD, basedir, O_RDONLY | O_DIRECTORY);
5757++ if (dirfd == -1) {
5858++ return -1;
5959++ }
6060++ }
6161++ int retfd = -1;
6262++
6363++ char *path_copy = my_strdup(relpath, __FILE__, __LINE__);
6464++ if (!path_copy) {
6565++ return -1;
6666++ }
6767++
6868++ for (const char *part = strtok(path_copy, "/");
6969++ part != NULL;
7070++ part = strtok(NULL, "/"))
7171++ {
7272++ int next_fd = openat(dirfd, part, O_RDONLY | O_DIRECTORY | O_NOFOLLOW);
7373++ if (next_fd == -1 && errno == ENOTDIR) {
7474++ if (strtok(NULL, "/") != NULL) {
7575++ // this is not the last component of the path
7676++ errno = ELOOP;
7777++ goto cleanup;
7878++ }
7979++ // this could be the last component of the path, try as a file
8080++ retfd = openat(dirfd, part, flags | O_NOFOLLOW, mode);
8181++ goto cleanup;
8282++ }
8383++ if (next_fd == -1) {
8484++ goto cleanup;
8585++ }
8686++ if (dirfd != AT_FDCWD) close(dirfd);
8787++ dirfd = next_fd;
8888++ }
8989++
9090++ // the path must be a directory
9191++ errno = EINVAL;
9292++
9393++cleanup:
9494++ free(path_copy);
9595++ if (dirfd != AT_FDCWD) {
9696++ close(dirfd);
9797++ }
9898++ return retfd;
9999++#endif // O_NOFOLLOW, O_DIRECTORY
100100++}
101101+--
102102+2.34.1
103103+
···11+From c78e53edb802d04f7e4e070fe8314f2544749e7a Mon Sep 17 00:00:00 2001
22+From: Andrew Tridgell <andrew@tridgell.net>
33+Date: Tue, 26 Nov 2024 09:16:31 +1100
44+Subject: [PATCH 4/4] disallow ../ elements in relpath for secure_relative_open
55+66+---
77+ syscall.c | 7 +++++++
88+ 1 file changed, 7 insertions(+)
99+1010+diff --git a/syscall.c b/syscall.c
1111+index a4b7f542..47c5ea57 100644
1212+--- a/syscall.c
1313++++ b/syscall.c
1414+@@ -721,6 +721,8 @@ int do_open_nofollow(const char *pathname, int flags)
1515+ must be a relative path, and the relpath must not contain any
1616+ elements in the path which follow symlinks (ie. like O_NOFOLLOW, but
1717+ applies to all path components, not just the last component)
1818++
1919++ The relpath must also not contain any ../ elements in the path
2020+ */
2121+ int secure_relative_open(const char *basedir, const char *relpath, int flags, mode_t mode)
2222+ {
2323+@@ -729,6 +731,11 @@ int secure_relative_open(const char *basedir, const char *relpath, int flags, mo
2424+ errno = EINVAL;
2525+ return -1;
2626+ }
2727++ if (strncmp(relpath, "../", 3) == 0 || strstr(relpath, "/../")) {
2828++ // no ../ elements allowed in the relpath
2929++ errno = EINVAL;
3030++ return -1;
3131++ }
3232+3333+ #if !defined(O_NOFOLLOW) || !defined(O_DIRECTORY)
3434+ // really old system, all we can do is live with the risks
3535+--
3636+2.34.1
3737+
···11+From 535f8f816539ba681ef0f12015d2cb587ae61b6d Mon Sep 17 00:00:00 2001
22+From: Andrew Tridgell <andrew@tridgell.net>
33+Date: Sat, 23 Nov 2024 15:15:53 +1100
44+Subject: [PATCH] make --safe-links stricter
55+66+when --safe-links is used also reject links where a '../' component is
77+included in the destination as other than the leading part of the
88+filename
99+---
1010+ testsuite/safe-links.test | 55 ++++++++++++++++++++++++++++++++++++
1111+ testsuite/unsafe-byname.test | 2 +-
1212+ util1.c | 26 ++++++++++++++++-
1313+ 3 files changed, 81 insertions(+), 2 deletions(-)
1414+ create mode 100644 testsuite/safe-links.test
1515+1616+diff --git a/testsuite/safe-links.test b/testsuite/safe-links.test
1717+new file mode 100644
1818+index 00000000..6e95a4b9
1919+--- /dev/null
2020++++ b/testsuite/safe-links.test
2121+@@ -0,0 +1,55 @@
2222++#!/bin/sh
2323++
2424++. "$suitedir/rsync.fns"
2525++
2626++test_symlink() {
2727++ is_a_link "$1" || test_fail "File $1 is not a symlink"
2828++}
2929++
3030++test_regular() {
3131++ if [ ! -f "$1" ]; then
3232++ test_fail "File $1 is not regular file or not exists"
3333++ fi
3434++}
3535++
3636++test_notexist() {
3737++ if [ -e "$1" ]; then
3838++ test_fail "File $1 exists"
3939++ fi
4040++ if [ -h "$1" ]; then
4141++ test_fail "File $1 exists as a symlink"
4242++ fi
4343++}
4444++
4545++cd "$tmpdir"
4646++
4747++mkdir from
4848++
4949++mkdir "from/safe"
5050++mkdir "from/unsafe"
5151++
5252++mkdir "from/safe/files"
5353++mkdir "from/safe/links"
5454++
5555++touch "from/safe/files/file1"
5656++touch "from/safe/files/file2"
5757++touch "from/unsafe/unsafefile"
5858++
5959++ln -s ../files/file1 "from/safe/links/"
6060++ln -s ../files/file2 "from/safe/links/"
6161++ln -s ../../unsafe/unsafefile "from/safe/links/"
6262++ln -s a/a/a/../../../unsafe2 "from/safe/links/"
6363++
6464++#echo "LISTING FROM"
6565++#ls -lR from
6666++
6767++echo "rsync with relative path and just -a"
6868++$RSYNC -avv --safe-links from/safe/ to
6969++
7070++#echo "LISTING TO"
7171++#ls -lR to
7272++
7373++test_symlink to/links/file1
7474++test_symlink to/links/file2
7575++test_notexist to/links/unsafefile
7676++test_notexist to/links/unsafe2
7777+diff --git a/testsuite/unsafe-byname.test b/testsuite/unsafe-byname.test
7878+index 75e72014..d2e318ef 100644
7979+--- a/testsuite/unsafe-byname.test
8080++++ b/testsuite/unsafe-byname.test
8181+@@ -40,7 +40,7 @@ test_unsafe ..//../dest from/dir unsafe
8282+ test_unsafe .. from/file safe
8383+ test_unsafe ../.. from/file unsafe
8484+ test_unsafe ..//.. from//file unsafe
8585+-test_unsafe dir/.. from safe
8686++test_unsafe dir/.. from unsafe
8787+ test_unsafe dir/../.. from unsafe
8888+ test_unsafe dir/..//.. from unsafe
8989+9090+diff --git a/util1.c b/util1.c
9191+index da50ff1e..f260d398 100644
9292+--- a/util1.c
9393++++ b/util1.c
9494+@@ -1318,7 +1318,14 @@ int handle_partial_dir(const char *fname, int create)
9595+ *
9696+ * "src" is the top source directory currently applicable at the level
9797+ * of the referenced symlink. This is usually the symlink's full path
9898+- * (including its name), as referenced from the root of the transfer. */
9999++ * (including its name), as referenced from the root of the transfer.
100100++ *
101101++ * NOTE: this also rejects dest names with a .. component in other
102102++ * than the first component of the name ie. it rejects names such as
103103++ * a/b/../x/y. This needs to be done as the leading subpaths 'a' or
104104++ * 'b' could later be replaced with symlinks such as a link to '.'
105105++ * resulting in the link being transferred now becoming unsafe
106106++ */
107107+ int unsafe_symlink(const char *dest, const char *src)
108108+ {
109109+ const char *name, *slash;
110110+@@ -1328,6 +1335,23 @@ int unsafe_symlink(const char *dest, const char *src)
111111+ if (!dest || !*dest || *dest == '/')
112112+ return 1;
113113+114114++ // reject destinations with /../ in the name other than at the start of the name
115115++ const char *dest2 = dest;
116116++ while (strncmp(dest2, "../", 3) == 0) {
117117++ dest2 += 3;
118118++ while (*dest2 == '/') {
119119++ // allow for ..//..///../foo
120120++ dest2++;
121121++ }
122122++ }
123123++ if (strstr(dest2, "/../"))
124124++ return 1;
125125++
126126++ // reject if the destination ends in /..
127127++ const size_t dlen = strlen(dest);
128128++ if (dlen > 3 && strcmp(&dest[dlen-3], "/..") == 0)
129129++ return 1;
130130++
131131+ /* find out what our safety margin is */
132132+ for (name = src; (slash = strchr(name, '/')) != 0; name = slash+1) {
133133+ /* ".." segment starts the count over. "." segment is ignored. */
134134+--
135135+2.34.1
136136+
···11+From 163e05b1680c4a3b448fa68d03c3fca9589f3bc4 Mon Sep 17 00:00:00 2001
22+From: Andrew Tridgell <andrew@tridgell.net>
33+Date: Tue, 10 Dec 2024 13:34:01 +1100
44+Subject: [PATCH 1/3] raise protocol version to 32
55+66+make it easier to spot unpatched servers
77+---
88+ rsync.h | 2 +-
99+ 1 file changed, 1 insertion(+), 1 deletion(-)
1010+1111+diff --git a/rsync.h b/rsync.h
1212+index b9a7101a..9be1297b 100644
1313+--- a/rsync.h
1414++++ b/rsync.h
1515+@@ -111,7 +111,7 @@
1616+1717+ /* Update this if you make incompatible changes and ALSO update the
1818+ * SUBPROTOCOL_VERSION if it is not a final (official) release. */
1919+-#define PROTOCOL_VERSION 31
2020++#define PROTOCOL_VERSION 32
2121+2222+ /* This is used when working on a new protocol version or for any unofficial
2323+ * protocol tweaks. It should be a non-zero value for each pre-release repo
2424+--
2525+2.34.1
2626+
···1212}:
13131414{
1515+ pname ? throw "You must provide either `name` or `pname`",
1616+ version ? throw "You must provide either `name` or `version`",
1717+ name ? "${pname}-${version}",
1518 runScript ? "bash",
1619 nativeBuildInputs ? [ ],
1720 extraInstallCommands ? "",
2121+ executableName ? args.pname or name,
1822 meta ? { },
1923 passthru ? { },
2024 extraPreBwrapCmds ? "",
···3034 ...
3135}@args:
32363333-assert (!args ? pname || !args ? version) -> (args ? name); # You must provide name if pname or version (preferred) is missing.
3737+# NOTE:
3838+# `pname` and `version` will throw if they were not provided.
3939+# Use `name` instead of directly evaluating `pname` or `version`.
4040+#
4141+# If you need `pname` or `version` sepcifically, use `args` instead:
4242+# e.g. `args.pname or ...`.
34433544let
3645 inherit (lib)
···4857 # explicit about which package set it's coming from.
4958 inherit (pkgsHostTarget) pkgsi686Linux;
50595151- name = args.name or "${args.pname}-${args.version}";
5252- executableName = args.pname or args.name;
5360 # we don't know which have been supplied, and want to avoid defaulting missing attrs to null. Passed into runCommandLocal
5461 nameAttrs = lib.filterAttrs (
5562 key: value:
···11-{ callPackage
22-, kernel ? null
33-, stdenv
44-, lib
55-, nixosTests
66-, ...
77-} @ args:
88-99-let
1010- stdenv' = if kernel == null then stdenv else kernel.stdenv;
1111-in
1212-callPackage ./generic.nix args {
1313- # You have to ensure that in `pkgs/top-level/linux-kernels.nix`
1414- # this attribute is the correct one for this package.
1515- kernelModuleAttribute = "zfs_2_1";
1616- # check the release notes for compatible kernels
1717- kernelCompatible = kernel: kernel.kernelOlder "6.8";
1818-1919- # This is a fixed version to the 2.1.x series, move only
2020- # if the 2.1.x series moves.
2121- version = "2.1.16";
2222-2323- hash = "sha256-egs7paAOdbRAJH4QwIjlK3jAL/le51kDQrdW4deHfAI=";
2424-2525- tests = {
2626- inherit (nixosTests.zfs) series_2_1;
2727- };
2828-2929- maintainers = [ lib.maintainers.raitobezarius ];
3030-}
+33
pkgs/os-specific/linux/zfs/2_3.nix
···11+{
22+ callPackage,
33+ kernel ? null,
44+ stdenv,
55+ lib,
66+ nixosTests,
77+ ...
88+}@args:
99+1010+let
1111+ stdenv' = if kernel == null then stdenv else kernel.stdenv;
1212+in
1313+callPackage ./generic.nix args {
1414+ # You have to ensure that in `pkgs/top-level/linux-kernels.nix`
1515+ # this attribute is the correct one for this package.
1616+ kernelModuleAttribute = "zfs_2_3";
1717+ # check the release notes for compatible kernels
1818+ kernelCompatible = kernel: kernel.kernelOlder "6.13";
1919+2020+ # this package should point to the latest release.
2121+ version = "2.3.0";
2222+2323+ tests = {
2424+ inherit (nixosTests.zfs) installer series_2_3;
2525+ };
2626+2727+ maintainers = with lib.maintainers; [
2828+ adamcstephens
2929+ amarshall
3030+ ];
3131+3232+ hash = "sha256-ZWWrVwMP/DSSIxuXp6GuHCD0wiRekHbRXFGaclqd/ns=";
3333+}
+2-2
pkgs/os-specific/linux/zfs/unstable.nix
···2121 # IMPORTANT: Always use a tagged release candidate or commits from the
2222 # zfs-<version>-staging branch, because this is tested by the OpenZFS
2323 # maintainers.
2424- version = "2.3.0-rc5";
2424+ version = "2.3.0";
2525 # rev = "";
26262727 tests = {
2828 inherit (nixosTests.zfs) unstable;
2929 };
30303131- hash = "sha256-gTpj1hYEkx+f/VvvfgeZeqwUhBVQyOIMKic8AaiwYzg=";
3131+ hash = "sha256-ZWWrVwMP/DSSIxuXp6GuHCD0wiRekHbRXFGaclqd/ns=";
32323333 extraLongDescription = ''
3434 This is "unstable" ZFS, and will usually be a pre-release version of ZFS.