···6Accepted arguments are:
78- `name`
9- The name of the environment, and the wrapper executable if `pname` is unset.
10- `pname`
11- The pname of the environment and the wrapper executable.
12- `version`
13 The version of the environment.
0014- `targetPkgs`
15 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.
16- `multiPkgs`
···6Accepted arguments are:
78- `name`
9+ The name of the environment.
10- `pname`
11+ The pname of the environment.
12- `version`
13 The version of the environment.
14+- `executableName`
15+ The name of the wrapper executable. Defaults to `pname` if set, or `name` otherwise.
16- `targetPkgs`
17 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.
18- `multiPkgs`
···84- Ensure that the introduced options are correct.
85 - Type should be appropriate (string related types differs in their merging capabilities, `loaOf` and `string` types are deprecated).
86 - Description, default and example should be provided.
00087- Ensure that module `meta` field is present
88 - Maintainers should be declared in `meta.maintainers`.
89 - Module documentation should be declared with `meta.doc`.
···84- Ensure that the introduced options are correct.
85 - Type should be appropriate (string related types differs in their merging capabilities, `loaOf` and `string` types are deprecated).
86 - Description, default and example should be provided.
87+ - Defaults may only be omitted if both:
88+ 1. The user is required to set the default in order to properly use the service.
89+ 2. The lack of a default does not break evaluation when the module is not enabled.
90- Ensure that module `meta` field is present
91 - Maintainers should be declared in `meta.maintainers`.
92 - Module documentation should be declared with `meta.doc`.
···1+From 33385aefe4773e7a3982d41995681eb079c92d12 Mon Sep 17 00:00:00 2001
2+From: Andrew Tridgell <andrew@tridgell.net>
3+Date: Sat, 23 Nov 2024 12:26:10 +1100
4+Subject: [PATCH 2/4] added secure_relative_open()
5+6+this is an open that enforces no symlink following for all path
7+components in a relative path
8+---
9+ syscall.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
10+ 1 file changed, 74 insertions(+)
11+12+diff --git a/syscall.c b/syscall.c
13+index d92074aa..a4b7f542 100644
14+--- a/syscall.c
15++++ b/syscall.c
16+@@ -33,6 +33,8 @@
17+ #include <sys/syscall.h>
18+ #endif
19+20++#include "ifuncs.h"
21++
22+ extern int dry_run;
23+ extern int am_root;
24+ extern int am_sender;
25+@@ -712,3 +714,75 @@ int do_open_nofollow(const char *pathname, int flags)
26+27+ return fd;
28+ }
29++
30++/*
31++ open a file relative to a base directory. The basedir can be NULL,
32++ in which case the current working directory is used. The relpath
33++ must be a relative path, and the relpath must not contain any
34++ elements in the path which follow symlinks (ie. like O_NOFOLLOW, but
35++ applies to all path components, not just the last component)
36++*/
37++int secure_relative_open(const char *basedir, const char *relpath, int flags, mode_t mode)
38++{
39++ if (!relpath || relpath[0] == '/') {
40++ // must be a relative path
41++ errno = EINVAL;
42++ return -1;
43++ }
44++
45++#if !defined(O_NOFOLLOW) || !defined(O_DIRECTORY)
46++ // really old system, all we can do is live with the risks
47++ if (!basedir) {
48++ return open(relpath, flags, mode);
49++ }
50++ char fullpath[MAXPATHLEN];
51++ pathjoin(fullpath, sizeof fullpath, basedir, relpath);
52++ return open(fullpath, flags, mode);
53++#else
54++ int dirfd = AT_FDCWD;
55++ if (basedir != NULL) {
56++ dirfd = openat(AT_FDCWD, basedir, O_RDONLY | O_DIRECTORY);
57++ if (dirfd == -1) {
58++ return -1;
59++ }
60++ }
61++ int retfd = -1;
62++
63++ char *path_copy = my_strdup(relpath, __FILE__, __LINE__);
64++ if (!path_copy) {
65++ return -1;
66++ }
67++
68++ for (const char *part = strtok(path_copy, "/");
69++ part != NULL;
70++ part = strtok(NULL, "/"))
71++ {
72++ int next_fd = openat(dirfd, part, O_RDONLY | O_DIRECTORY | O_NOFOLLOW);
73++ if (next_fd == -1 && errno == ENOTDIR) {
74++ if (strtok(NULL, "/") != NULL) {
75++ // this is not the last component of the path
76++ errno = ELOOP;
77++ goto cleanup;
78++ }
79++ // this could be the last component of the path, try as a file
80++ retfd = openat(dirfd, part, flags | O_NOFOLLOW, mode);
81++ goto cleanup;
82++ }
83++ if (next_fd == -1) {
84++ goto cleanup;
85++ }
86++ if (dirfd != AT_FDCWD) close(dirfd);
87++ dirfd = next_fd;
88++ }
89++
90++ // the path must be a directory
91++ errno = EINVAL;
92++
93++cleanup:
94++ free(path_copy);
95++ if (dirfd != AT_FDCWD) {
96++ close(dirfd);
97++ }
98++ return retfd;
99++#endif // O_NOFOLLOW, O_DIRECTORY
100++}
101+--
102+2.34.1
103+
···1+From c78e53edb802d04f7e4e070fe8314f2544749e7a Mon Sep 17 00:00:00 2001
2+From: Andrew Tridgell <andrew@tridgell.net>
3+Date: Tue, 26 Nov 2024 09:16:31 +1100
4+Subject: [PATCH 4/4] disallow ../ elements in relpath for secure_relative_open
5+6+---
7+ syscall.c | 7 +++++++
8+ 1 file changed, 7 insertions(+)
9+10+diff --git a/syscall.c b/syscall.c
11+index a4b7f542..47c5ea57 100644
12+--- a/syscall.c
13++++ b/syscall.c
14+@@ -721,6 +721,8 @@ int do_open_nofollow(const char *pathname, int flags)
15+ must be a relative path, and the relpath must not contain any
16+ elements in the path which follow symlinks (ie. like O_NOFOLLOW, but
17+ applies to all path components, not just the last component)
18++
19++ The relpath must also not contain any ../ elements in the path
20+ */
21+ int secure_relative_open(const char *basedir, const char *relpath, int flags, mode_t mode)
22+ {
23+@@ -729,6 +731,11 @@ int secure_relative_open(const char *basedir, const char *relpath, int flags, mo
24+ errno = EINVAL;
25+ return -1;
26+ }
27++ if (strncmp(relpath, "../", 3) == 0 || strstr(relpath, "/../")) {
28++ // no ../ elements allowed in the relpath
29++ errno = EINVAL;
30++ return -1;
31++ }
32+33+ #if !defined(O_NOFOLLOW) || !defined(O_DIRECTORY)
34+ // really old system, all we can do is live with the risks
35+--
36+2.34.1
37+
···1+From 535f8f816539ba681ef0f12015d2cb587ae61b6d Mon Sep 17 00:00:00 2001
2+From: Andrew Tridgell <andrew@tridgell.net>
3+Date: Sat, 23 Nov 2024 15:15:53 +1100
4+Subject: [PATCH] make --safe-links stricter
5+6+when --safe-links is used also reject links where a '../' component is
7+included in the destination as other than the leading part of the
8+filename
9+---
10+ testsuite/safe-links.test | 55 ++++++++++++++++++++++++++++++++++++
11+ testsuite/unsafe-byname.test | 2 +-
12+ util1.c | 26 ++++++++++++++++-
13+ 3 files changed, 81 insertions(+), 2 deletions(-)
14+ create mode 100644 testsuite/safe-links.test
15+16+diff --git a/testsuite/safe-links.test b/testsuite/safe-links.test
17+new file mode 100644
18+index 00000000..6e95a4b9
19+--- /dev/null
20++++ b/testsuite/safe-links.test
21+@@ -0,0 +1,55 @@
22++#!/bin/sh
23++
24++. "$suitedir/rsync.fns"
25++
26++test_symlink() {
27++ is_a_link "$1" || test_fail "File $1 is not a symlink"
28++}
29++
30++test_regular() {
31++ if [ ! -f "$1" ]; then
32++ test_fail "File $1 is not regular file or not exists"
33++ fi
34++}
35++
36++test_notexist() {
37++ if [ -e "$1" ]; then
38++ test_fail "File $1 exists"
39++ fi
40++ if [ -h "$1" ]; then
41++ test_fail "File $1 exists as a symlink"
42++ fi
43++}
44++
45++cd "$tmpdir"
46++
47++mkdir from
48++
49++mkdir "from/safe"
50++mkdir "from/unsafe"
51++
52++mkdir "from/safe/files"
53++mkdir "from/safe/links"
54++
55++touch "from/safe/files/file1"
56++touch "from/safe/files/file2"
57++touch "from/unsafe/unsafefile"
58++
59++ln -s ../files/file1 "from/safe/links/"
60++ln -s ../files/file2 "from/safe/links/"
61++ln -s ../../unsafe/unsafefile "from/safe/links/"
62++ln -s a/a/a/../../../unsafe2 "from/safe/links/"
63++
64++#echo "LISTING FROM"
65++#ls -lR from
66++
67++echo "rsync with relative path and just -a"
68++$RSYNC -avv --safe-links from/safe/ to
69++
70++#echo "LISTING TO"
71++#ls -lR to
72++
73++test_symlink to/links/file1
74++test_symlink to/links/file2
75++test_notexist to/links/unsafefile
76++test_notexist to/links/unsafe2
77+diff --git a/testsuite/unsafe-byname.test b/testsuite/unsafe-byname.test
78+index 75e72014..d2e318ef 100644
79+--- a/testsuite/unsafe-byname.test
80++++ b/testsuite/unsafe-byname.test
81+@@ -40,7 +40,7 @@ test_unsafe ..//../dest from/dir unsafe
82+ test_unsafe .. from/file safe
83+ test_unsafe ../.. from/file unsafe
84+ test_unsafe ..//.. from//file unsafe
85+-test_unsafe dir/.. from safe
86++test_unsafe dir/.. from unsafe
87+ test_unsafe dir/../.. from unsafe
88+ test_unsafe dir/..//.. from unsafe
89+90+diff --git a/util1.c b/util1.c
91+index da50ff1e..f260d398 100644
92+--- a/util1.c
93++++ b/util1.c
94+@@ -1318,7 +1318,14 @@ int handle_partial_dir(const char *fname, int create)
95+ *
96+ * "src" is the top source directory currently applicable at the level
97+ * of the referenced symlink. This is usually the symlink's full path
98+- * (including its name), as referenced from the root of the transfer. */
99++ * (including its name), as referenced from the root of the transfer.
100++ *
101++ * NOTE: this also rejects dest names with a .. component in other
102++ * than the first component of the name ie. it rejects names such as
103++ * a/b/../x/y. This needs to be done as the leading subpaths 'a' or
104++ * 'b' could later be replaced with symlinks such as a link to '.'
105++ * resulting in the link being transferred now becoming unsafe
106++ */
107+ int unsafe_symlink(const char *dest, const char *src)
108+ {
109+ const char *name, *slash;
110+@@ -1328,6 +1335,23 @@ int unsafe_symlink(const char *dest, const char *src)
111+ if (!dest || !*dest || *dest == '/')
112+ return 1;
113+114++ // reject destinations with /../ in the name other than at the start of the name
115++ const char *dest2 = dest;
116++ while (strncmp(dest2, "../", 3) == 0) {
117++ dest2 += 3;
118++ while (*dest2 == '/') {
119++ // allow for ..//..///../foo
120++ dest2++;
121++ }
122++ }
123++ if (strstr(dest2, "/../"))
124++ return 1;
125++
126++ // reject if the destination ends in /..
127++ const size_t dlen = strlen(dest);
128++ if (dlen > 3 && strcmp(&dest[dlen-3], "/..") == 0)
129++ return 1;
130++
131+ /* find out what our safety margin is */
132+ for (name = src; (slash = strchr(name, '/')) != 0; name = slash+1) {
133+ /* ".." segment starts the count over. "." segment is ignored. */
134+--
135+2.34.1
136+
···1+From 163e05b1680c4a3b448fa68d03c3fca9589f3bc4 Mon Sep 17 00:00:00 2001
2+From: Andrew Tridgell <andrew@tridgell.net>
3+Date: Tue, 10 Dec 2024 13:34:01 +1100
4+Subject: [PATCH 1/3] raise protocol version to 32
5+6+make it easier to spot unpatched servers
7+---
8+ rsync.h | 2 +-
9+ 1 file changed, 1 insertion(+), 1 deletion(-)
10+11+diff --git a/rsync.h b/rsync.h
12+index b9a7101a..9be1297b 100644
13+--- a/rsync.h
14++++ b/rsync.h
15+@@ -111,7 +111,7 @@
16+17+ /* Update this if you make incompatible changes and ALSO update the
18+ * SUBPROTOCOL_VERSION if it is not a final (official) release. */
19+-#define PROTOCOL_VERSION 31
20++#define PROTOCOL_VERSION 32
21+22+ /* This is used when working on a new protocol version or for any unofficial
23+ * protocol tweaks. It should be a non-zero value for each pre-release repo
24+--
25+2.34.1
26+
···12}:
1314{
00015 runScript ? "bash",
16 nativeBuildInputs ? [ ],
17 extraInstallCommands ? "",
018 meta ? { },
19 passthru ? { },
20 extraPreBwrapCmds ? "",
···30 ...
31}@args:
3233-assert (!args ? pname || !args ? version) -> (args ? name); # You must provide name if pname or version (preferred) is missing.
000003435let
36 inherit (lib)
···48 # explicit about which package set it's coming from.
49 inherit (pkgsHostTarget) pkgsi686Linux;
5051- name = args.name or "${args.pname}-${args.version}";
52- executableName = args.pname or args.name;
53 # we don't know which have been supplied, and want to avoid defaulting missing attrs to null. Passed into runCommandLocal
54 nameAttrs = lib.filterAttrs (
55 key: value:
···12}:
1314{
15+ pname ? throw "You must provide either `name` or `pname`",
16+ version ? throw "You must provide either `name` or `version`",
17+ name ? "${pname}-${version}",
18 runScript ? "bash",
19 nativeBuildInputs ? [ ],
20 extraInstallCommands ? "",
21+ executableName ? args.pname or name,
22 meta ? { },
23 passthru ? { },
24 extraPreBwrapCmds ? "",
···34 ...
35}@args:
3637+# NOTE:
38+# `pname` and `version` will throw if they were not provided.
39+# Use `name` instead of directly evaluating `pname` or `version`.
40+#
41+# If you need `pname` or `version` sepcifically, use `args` instead:
42+# e.g. `args.pname or ...`.
4344let
45 inherit (lib)
···57 # explicit about which package set it's coming from.
58 inherit (pkgsHostTarget) pkgsi686Linux;
590060 # we don't know which have been supplied, and want to avoid defaulting missing attrs to null. Passed into runCommandLocal
61 nameAttrs = lib.filterAttrs (
62 key: value:
···126 [
127 zlib
128 cyrus_sasl
0129 ]
130 # Darwin doesn't have libuuid, try to build without it
131 ++ lib.optional (!stdenv.hostPlatform.isDarwin) libuuid;
···126 [
127 zlib
128 cyrus_sasl
129+ sqlite
130 ]
131 # Darwin doesn't have libuuid, try to build without it
132 ++ lib.optional (!stdenv.hostPlatform.isDarwin) libuuid;
···142 gappsWrapperArgs+=(
143 # For sysprof-agent
144 --prefix PATH : "${sysprof}/bin"
00145 )
146147 # Ensure that all plugins get their interpreter paths fixed up.
···142 gappsWrapperArgs+=(
143 # For sysprof-agent
144 --prefix PATH : "${sysprof}/bin"
145+ # libpanel icons
146+ --prefix XDG_DATA_DIRS : "${libpanel}/share"
147 )
148149 # Ensure that all plugins get their interpreter paths fixed up.
···1-{ callPackage
2-, kernel ? null
3-, stdenv
4-, lib
5-, nixosTests
6-, ...
7-} @ args:
8-9-let
10- stdenv' = if kernel == null then stdenv else kernel.stdenv;
11-in
12-callPackage ./generic.nix args {
13- # You have to ensure that in `pkgs/top-level/linux-kernels.nix`
14- # this attribute is the correct one for this package.
15- kernelModuleAttribute = "zfs_2_1";
16- # check the release notes for compatible kernels
17- kernelCompatible = kernel: kernel.kernelOlder "6.8";
18-19- # This is a fixed version to the 2.1.x series, move only
20- # if the 2.1.x series moves.
21- version = "2.1.16";
22-23- hash = "sha256-egs7paAOdbRAJH4QwIjlK3jAL/le51kDQrdW4deHfAI=";
24-25- tests = {
26- inherit (nixosTests.zfs) series_2_1;
27- };
28-29- maintainers = [ lib.maintainers.raitobezarius ];
30-}
···000000000000000000000000000000
+33
pkgs/os-specific/linux/zfs/2_3.nix
···000000000000000000000000000000000
···1+{
2+ callPackage,
3+ kernel ? null,
4+ stdenv,
5+ lib,
6+ nixosTests,
7+ ...
8+}@args:
9+10+let
11+ stdenv' = if kernel == null then stdenv else kernel.stdenv;
12+in
13+callPackage ./generic.nix args {
14+ # You have to ensure that in `pkgs/top-level/linux-kernels.nix`
15+ # this attribute is the correct one for this package.
16+ kernelModuleAttribute = "zfs_2_3";
17+ # check the release notes for compatible kernels
18+ kernelCompatible = kernel: kernel.kernelOlder "6.13";
19+20+ # this package should point to the latest release.
21+ version = "2.3.0";
22+23+ tests = {
24+ inherit (nixosTests.zfs) installer series_2_3;
25+ };
26+27+ maintainers = with lib.maintainers; [
28+ adamcstephens
29+ amarshall
30+ ];
31+32+ hash = "sha256-ZWWrVwMP/DSSIxuXp6GuHCD0wiRekHbRXFGaclqd/ns=";
33+}
+2-2
pkgs/os-specific/linux/zfs/unstable.nix
···21 # IMPORTANT: Always use a tagged release candidate or commits from the
22 # zfs-<version>-staging branch, because this is tested by the OpenZFS
23 # maintainers.
24- version = "2.3.0-rc5";
25 # rev = "";
2627 tests = {
28 inherit (nixosTests.zfs) unstable;
29 };
3031- hash = "sha256-gTpj1hYEkx+f/VvvfgeZeqwUhBVQyOIMKic8AaiwYzg=";
3233 extraLongDescription = ''
34 This is "unstable" ZFS, and will usually be a pre-release version of ZFS.
···21 # IMPORTANT: Always use a tagged release candidate or commits from the
22 # zfs-<version>-staging branch, because this is tested by the OpenZFS
23 # maintainers.
24+ version = "2.3.0";
25 # rev = "";
2627 tests = {
28 inherit (nixosTests.zfs) unstable;
29 };
3031+ hash = "sha256-ZWWrVwMP/DSSIxuXp6GuHCD0wiRekHbRXFGaclqd/ns=";
3233 extraLongDescription = ''
34 This is "unstable" ZFS, and will usually be a pre-release version of ZFS.