Bug 1394962 - Review Request: clevis - Automated decryption framework
Summary: Review Request: clevis - Automated decryption framework
Keywords:
Status: CLOSED CURRENTRELEASE
Alias: None
Product: Fedora
Classification: Fedora
Component: Package Review
Version: rawhide
Hardware: All
OS: Linux
medium
medium
Target Milestone: ---
Assignee: Zbigniew Jędrzejewski-Szmek
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2016-11-14 21:42 UTC by Nathaniel McCallum
Modified: 2019-09-17 15:48 UTC (History)
2 users (show)

Fixed In Version:
Doc Type: If docs needed, set a value
Doc Text:
Clone Of:
Environment:
Last Closed: 2019-09-17 15:48:49 UTC
Type: ---
Embargoed:
zbyszek: fedora-review+


Attachments (Terms of Use)

Comment 1 Zbigniew Jędrzejewski-Szmek 2016-11-15 19:22:13 UTC
%description
Clevis is a framework for automated decryption.
→ great, but please provide some detail here. Automated decryption of what? Is this another jack the ripper clone?

make %{?_smp_mflags} V=1
make %{?_smp_mflags} check
→ %make_build V=1
  %make_build check

rm -rf $RPM_BUILD_ROOT
→ please no [https://fedoraproject.org/wiki/Packaging:Guidelines#Tags_and_Sections]

Fedora review says:
Issues:
=======
- Package installs a %{name}.desktop using desktop-file-install or desktop-
  file-validate if there is such a file.
- Package uses hardened build flags if required to.
  Note: suid files: clevis-luks-udisks2 and not %global _hardened_build
  See:
  http://fedoraproject.org/wiki/Packaging:Guidelines?rd=Packaging/Guidelines#Compiler_flags

rpmlint:
clevis-udisks2.x86_64: W: non-conffile-in-etc /etc/xdg/autostart/clevis-luks-udisks2.desktop

Comment 3 Nathaniel McCallum 2016-11-15 21:36:01 UTC
I'm not precisely sure what you want me to do with the .desktop file. This is not a general purpose application but a user session daemon.

Comment 4 Zbigniew Jędrzejewski-Szmek 2016-11-15 21:49:50 UTC
I should have pasted a link to the guidelines:
https://fedoraproject.org/wiki/Packaging:Guidelines#Desktop_files
You must either use desktop-file-install of desktop-file-validate.

Comment 5 Zbigniew Jędrzejewski-Szmek 2016-11-15 21:53:20 UTC
Also, I'm still stumped a bit by the %description... Imagine that you're a user who looks and 'dnf info' output:
Clevis is a framework for automated decryption. It allows you to encrypt
data using sophisticated unlocking policies which enable decryption to
occur automatically.

It doesn't say *what* is being decrypted. It also gives no hint what those "sophisticated unlocking policies" might be. A package should not be a black box... Please make this a bit easier to understand.

Comment 6 Nathaniel McCallum 2016-11-15 22:11:09 UTC
(In reply to Zbigniew Jędrzejewski-Szmek from comment #5)
> Also, I'm still stumped a bit by the %description... Imagine that you're a
> user who looks and 'dnf info' output:
> Clevis is a framework for automated decryption. It allows you to encrypt
> data using sophisticated unlocking policies which enable decryption to
> occur automatically.
> 
> It doesn't say *what* is being decrypted. It also gives no hint what those
> "sophisticated unlocking policies" might be. A package should not be a black
> box... Please make this a bit easier to understand.

Anything is being encrypted/decrypted. You're asking for more specificity in the description of a subpackage that is the enabling technology for other subpackages. The clevis package provides basic encryption/decryption policy support. Users can use this directly. But most commonly, it will be used as a building block for other packages.

For example, you can install clevis-dracut (which depends on clevis and clevis-luks) to perform automated root volume decryption.

Simply put, the clevis package is the core functionality and is intentionally vague.

Comment 7 Nathaniel McCallum 2016-11-15 22:12:50 UTC
(In reply to Zbigniew Jędrzejewski-Szmek from comment #4)
> I should have pasted a link to the guidelines:
> https://fedoraproject.org/wiki/Packaging:Guidelines#Desktop_files
> You must either use desktop-file-install of desktop-file-validate.

As I stated above, this is not a usual .desktop file. It is not an application, but a user session daemon. I do not believe these requirements apply in this situation.

Comment 8 Zbigniew Jędrzejewski-Szmek 2016-11-16 02:04:17 UTC
There's nothing in the guidelines that says that desktop file validation should not be performed in this case. This file is installed into the same directory as many other .desktop files, so it'll be loaded by various tools, so I think it should be validated. desktop-file-validate prints no warnings for clevis-luks-udisks2.desktop, so I don't see any reason to not validate it according to the guidelines.

> The clevis package provides basic encryption/decryption policy support. Users can use this directly. But most commonly, it will be used as a building block for other packages, [for example to automatically decrypt LUKS volumes using a passphrase received over the network, including the root volume, see clevis-lukus and clevis-dracut packages].

OK, great, I think that if this is appended to current %description, it gives a reasonable idea what this package does.

Comment 9 Zbigniew Jędrzejewski-Szmek 2016-11-16 05:03:25 UTC
I saw the that one of the files is suid, so I decided to have a look
at the code...

Two issues pop out:
1. memset(key, 0, strlen(key)); is going to be optimized away. If you
are doing that to decrease chances of the key leaking out, this will
not work. See
https://github.com/systemd/systemd/blob/493fd52f1ada36bfe63301d4bb50f7fd2b38c670/src/basic/string-\
util.c#L834
for a way (cribbed from openssl), for a way around that.

2. I don't think using the relative path like as in
snprintf(path, pathl, "%s/../bin/clevis-decrypt", dirname(tmp))
is safe. If the user is able to call the binary under a different
path where they control the ../bin prefix, it will allow them to call
arbitrary binary as root. I don't think it's directly exploitable in
the default configuration, but it's not hard to contrive some scenario
where it would be:

- fs.protected_hardlinks=0
  This is the kernel default, which is overridden by systemd-sysctl
  after boot.  If systemd-sysctl is prevented from running, for
  example by broken configuration, clevis-luks-udisks2 becomes
  immediately exploitable a la CVE-2009-1894.

- some scenario where the fs containing the suid binary is mounted
  below a user writable directory (for example the administrator
  temporarily mounts the fs under /var/tmp for backup purposes).

- some manipulation using mount namespaces.

I don't see an exploit, but relying on the binary always being visible
only under the correct path seems very brittle. It'd seem much better
to substitute the real absolute path during build.

Comment 10 Nathaniel McCallum 2016-11-16 05:25:38 UTC
(In reply to Zbigniew Jędrzejewski-Szmek from comment #9)
> I saw the that one of the files is suid, so I decided to have a look
> at the code...
> 
> Two issues pop out:
> 1. memset(key, 0, strlen(key)); is going to be optimized away. If you
> are doing that to decrease chances of the key leaking out, this will
> not work. See
> https://github.com/systemd/systemd/blob/
> 493fd52f1ada36bfe63301d4bb50f7fd2b38c670/src/basic/string-\
> util.c#L834
> for a way (cribbed from openssl), for a way around that.
> 
> 2. I don't think using the relative path like as in
> snprintf(path, pathl, "%s/../bin/clevis-decrypt", dirname(tmp))
> is safe. If the user is able to call the binary under a different
> path where they control the ../bin prefix, it will allow them to call
> arbitrary binary as root.

The clevis-decrypt binary is not executed as root. We drop privileges much earlier than that. See: https://github.com/latchset/clevis/blob/master/clevis-luks-udisks2.c#L384

However, your concern is still valid because we pass information obtained as root to that process. So it still represents a security concern. I'd love to chat with you on IRC to discuss some of my concerns with my own code if you have time.

> I don't think it's directly exploitable in
> the default configuration, but it's not hard to contrive some scenario
> where it would be:
> 
> - fs.protected_hardlinks=0
>   This is the kernel default, which is overridden by systemd-sysctl
>   after boot.  If systemd-sysctl is prevented from running, for
>   example by broken configuration, clevis-luks-udisks2 becomes
>   immediately exploitable a la CVE-2009-1894.
> 
> - some scenario where the fs containing the suid binary is mounted
>   below a user writable directory (for example the administrator
>   temporarily mounts the fs under /var/tmp for backup purposes).
> 
> - some manipulation using mount namespaces.
> 
> I don't see an exploit, but relying on the binary always being visible
> only under the correct path seems very brittle. It'd seem much better
> to substitute the real absolute path during build.

Yeah, I agree. The main reason I haven't done this is because it makes in-tree unit testing (after build, before install) more difficult. Suggestions welcome.

Comment 11 Zbigniew Jędrzejewski-Szmek 2016-11-16 15:00:24 UTC
(In reply to Nathaniel McCallum from comment #10)
> The clevis-decrypt binary is not executed as root. We drop privileges much
> earlier than that. See:
> https://github.com/latchset/clevis/blob/master/clevis-luks-udisks2.c#L384
> 
> However, your concern is still valid because we pass information obtained as
> root to that process. So it still represents a security concern. I'd love to
> chat with you on IRC to discuss some of my concerns with my own code if you
> have time.

Yeah, I think it's a concern, also because the program uses the information
received *from* the other binary.

Please ping me on IRC when you're around. I saw your ping yesterday after I
returned home, but you were already gone...

> Yeah, I agree. The main reason I haven't done this is because it makes
> in-tree unit testing (after build, before install) more difficult.
> Suggestions welcome.

I'd add a C define with the full path (using AC_DEFINE or similar), and
allow overriding it using a shell variable in non-suid process.

const char *p = secure_getenv("CLEVIS_HELPER_PATH");
if (p)
       return p;
else
       return HELPER_PATH;

Comment 12 Nathaniel McCallum 2016-11-17 23:11:09 UTC
I've fixed most issues upstream. Unfortunately, I also discovered a GCC bug which effects clevis. I've added a reference to that bug here. Once it is resolved, I'll get a new SRPM ready for testing.

Comment 13 Nathaniel McCallum 2016-11-18 16:50:24 UTC
SPEC: http://copr-dist-git.fedorainfracloud.org/cgit/npmccallum/clevis/clevis.git/plain/clevis.spec
SRPM: https://copr-be.cloud.fedoraproject.org/results/npmccallum/clevis/fedora-rawhide-x86_64/00478613-clevis/clevis-2-1.fc26.src.rpm

This includes the new upstream release (v2) which works around the GCC code generation issue. It also runs "clevis decrypt" as root, so the key is protected (though running network code as root is somewhat less than ideal; this can be addressed in future releases).

Comment 14 Zbigniew Jędrzejewski-Szmek 2016-11-18 18:17:14 UTC
Package Review
==============

Legend:
[x] = Pass, [!] = Fail, [-] = Not applicable, [?] = Not evaluated

===== MUST items =====

C/C++:
[x]: Package does not contain kernel modules.
[x]: Package contains no static executables.
[x]: Header files in -devel subpackage, if present.
[x]: Package does not contain any libtool archives (.la)
[x]: Rpath absent or only used for internal libs.

Generic:
[x]: Package is licensed with an open-source compatible license and meets
     other legal requirements as defined in the legal section of Packaging
     Guidelines.
GPLv3+

[x]: License field in the package spec file matches the actual license.
     Note: Checking patched sources after %prep for licenses. Licenses
     found: "MIT/X11 (BSD like)", "GPL (v3 or later)", "Unknown or
     generated". 9 files have unknown license. Detailed output of
     licensecheck in /var/tmp/1394962-clevis/licensecheck.txt
[x]: License file installed when any subpackage combination is installed.
Yes, all packages transitively depend on clevis.rpm which has the license.

[!]: Package requires other packages for directories it uses.
     Note: No known owner of /usr/lib/dracut/modules.d/60clevis
[!]: Package must own all directories that it creates.
     Note: Directories without known owners:
     /usr/lib/dracut/modules.d/60clevis
Please add %dir /usr/lib/dracut/modules.d/60clevis to %files.

[x]: %build honors applicable compiler flags or justifies otherwise.
[x]: Package contains no bundled libraries without FPC exception.
[x]: Changelog in prescribed format.
[x]: Sources contain only permissible code or content.
[-]: Development files must be in a -devel package
[x]: Package uses nothing in %doc for runtime.
[x]: Package consistently uses macros (instead of hard-coded directory
     names).
[x]: Package is named according to the Package Naming Guidelines.
[x]: Package does not generate any conflict.
[x]: Package obeys FHS, except libexecdir and /usr/target.
[-]: If the package is a rename of another package, proper Obsoletes and
     Provides are present.
[x]: Requires correct, justified where necessary.
[x]: Spec file is legible and written in American English.
[x]: Useful -debuginfo package or justification otherwise.
[x]: Package is not known to require an ExcludeArch tag.
[x]: Package complies to the Packaging Guidelines
[x]: Package successfully compiles and builds into binary rpms on at least
     one supported primary architecture.
[x]: Package installs properly.
[x]: Rpmlint is run on all rpms the build produces.
     Note: There are rpmlint messages (see attachment).
[x]: If (and only if) the source package includes the text of the
     license(s) in its own file, then that file, containing the text of the
     license(s) for the package is included in %license.
[x]: Package does not own files or directories owned by other packages.
[x]: All build dependencies are listed in BuildRequires, except for any
     that are listed in the exceptions section of Packaging Guidelines.
[x]: Package uses either %{buildroot} or $RPM_BUILD_ROOT
[x]: Package does not run rm -rf %{buildroot} (or $RPM_BUILD_ROOT) at the
     beginning of %install.
[x]: Package uses hardened build flags if required to.
     Note: suid files: clevis-luks-udisks2
[x]: Macros in Summary, %description expandable at SRPM build time.
[x]: Package contains desktop file if it is a GUI application.
[x]: Package installs a %{name}.desktop using desktop-file-install or
     desktop-file-validate if there is such a file.
[x]: Dist tag is present.
[x]: Package does not contain duplicates in %files.
[x]: Package use %makeinstall only when make install DESTDIR=... doesn't
     work.
[x]: Package is named using only allowed ASCII characters.
[x]: Package does not use a name that already exists.
[x]: Package is not relocatable.
[x]: Sources used to build the package match the upstream source, as
     provided in the spec URL.
[x]: Spec file name must match the spec package %{name}, in the format
     %{name}.spec.
[x]: Package contains systemd file(s) if in need.
[x]: File names are valid UTF-8.
[x]: Large documentation must go in a -doc subpackage. Large could be size
     (~1MB) or number of files.
     Note: Documentation size is 0 bytes in 0 files.
[x]: Packages must not store files under /srv, /opt or /usr/local

===== SHOULD items =====

Generic:
[-]: If the source package does not include license text(s) as a separate
     file from upstream, the packager SHOULD query upstream to include it.
[x]: Final provides and requires are sane (see attachments).
[x]: Fully versioned dependency in subpackages if applicable.
     Note: No Requires: %{name}%{?_isa} = %{version}-%{release} in clevis-
     dracut , clevis-udisks2 , clevis-debuginfo
clevis-dracut -> clevis-luks -> clevis
clevis-udisks2 -> clevis-luks -> clevis

[-]: Package functions as described.
Not checked. I don't have a server set up that clevis could talk to.

[x]: Latest version is packaged.
[x]: Package does not include license text files separate from upstream.
[-]: Description and summary sections in the package spec file contains
     translations for supported Non-English languages, if available.
[x]: Package should compile and build into binary rpms on all supported
     architectures.
[x]: %check is present and all tests pass.
[x]: Packages should try to preserve timestamps of original installed
     files.
[x]: Reviewer should test that the package builds in mock.
[x]: Buildroot is not present
[x]: Package has no %clean section with rm -rf %{buildroot} (or
     $RPM_BUILD_ROOT)
[x]: No file requires outside of /etc, /bin, /sbin, /usr/bin, /usr/sbin.
[x]: Packager, Vendor, PreReq, Copyright tags should not be in spec file
[x]: Sources can be downloaded from URI in Source: tag
[x]: SourceX is a working URL.
[x]: Spec use %global instead of %define unless justified.

===== EXTRA items =====

Generic:
[x]: Rpmlint is run on debuginfo package(s).
     Note: No rpmlint messages.
[x]: Rpmlint is run on all installed packages.
     Note: There are rpmlint messages (see attachment).
[x]: Large data in /usr/share should live in a noarch subpackage if package
     is arched.
[x]: Spec file according to URL is the same as in SRPM.


Rpmlint
-------
Checking: clevis-2-1.fc26.x86_64.rpm
          clevis-luks-2-1.fc26.x86_64.rpm
          clevis-dracut-2-1.fc26.x86_64.rpm
          clevis-udisks2-2-1.fc26.x86_64.rpm
          clevis-debuginfo-2-1.fc26.x86_64.rpm
          clevis-2-1.fc26.src.rpm
clevis.x86_64: W: spelling-error %description -l en_US luks -> looks, lurks, lucks
clevis.x86_64: W: spelling-error %description -l en_US dracut -> Dracula
clevis.x86_64: W: no-documentation
clevis-luks.x86_64: W: spelling-error %description -l en_US unlocker -> unlocked, unlock er, unlock-er
clevis-luks.x86_64: W: spelling-error %description -l en_US dracut -> Dracula
clevis-luks.x86_64: W: no-documentation
clevis-dracut.x86_64: W: only-non-binary-in-usr-lib
clevis-dracut.x86_64: W: no-documentation
clevis-udisks2.x86_64: W: spelling-error %description -l en_US storaged -> storage, storage d, stored
clevis-udisks2.x86_64: W: no-documentation
clevis.src: W: spelling-error %description -l en_US luks -> looks, lurks, lucks
All OK.

clevis.x86_64: W: no-manual-page-for-binary clevis
More docs would be nice ;)

clevis-udisks2.x86_64: E: setuid-binary /usr/libexec/clevis-luks-udisks2 root 4755
clevis-udisks2.x86_64: E: non-standard-executable-perm /usr/libexec/clevis-luks-udisks2 4755
OK.

clevis-udisks2.x86_64: W: non-conffile-in-etc /etc/xdg/autostart/clevis-luks-udisks2.desktop
Despite the location, this is not a config file. Not using %config
matches what other packages which install files there are doing.
Somebody should move the whole lot to /usr.

clevis.src:90: E: hardcoded-library-path in %{_prefix}/lib/dracut/modules.d/60%{name}/module-setup.sh
clevis.src:91: E: hardcoded-library-path in %{_prefix}/lib/dracut/modules.d/60%{name}/%{name}-hook.sh
That's OK too, I think.

6 packages and 0 specfiles checked; 4 errors, 13 warnings.

Rpmlint (debuginfo)
-------------------
Checking: clevis-debuginfo-2-1.fc26.x86_64.rpm
1 packages and 0 specfiles checked; 0 errors, 0 warnings.

Requires
--------
clevis-debuginfo (rpmlib, GLIBC filtered):

clevis-udisks2 (rpmlib, GLIBC filtered):
    clevis-luks(x86-64)
    libc.so.6()(64bit)
    libcryptsetup.so.4()(64bit)
    libcryptsetup.so.4(CRYPTSETUP_1.0)(64bit)
    libgio-2.0.so.0()(64bit)
    libglib-2.0.so.0()(64bit)
    libgobject-2.0.so.0()(64bit)
    libhttp_parser.so.2()(64bit)
    libluksmeta.so.0()(64bit)
    libpthread.so.0()(64bit)
    libudisks2.so.0()(64bit)
    rtld(GNU_HASH)

clevis-luks (rpmlib, GLIBC filtered):
    /bin/bash
    clevis(x86-64)
    cryptsetup
    luksmeta

clevis (rpmlib, GLIBC filtered):
    /bin/bash
    coreutils
    libc.so.6()(64bit)
    libcrypto.so.1.1()(64bit)
    libcrypto.so.1.1(OPENSSL_1_1_0)(64bit)
    libgcc_s.so.1()(64bit)
    libgcc_s.so.1(GCC_3.0)(64bit)
    libgcc_s.so.1(GCC_3.3.1)(64bit)
    libhttp_parser.so.2()(64bit)
    libjansson.so.4()(64bit)
    libjose-openssl.so.0()(64bit)
    libjose-zlib.so.0()(64bit)
    libjose.so.0()(64bit)
    libpthread.so.0()(64bit)
    rtld(GNU_HASH)

clevis-dracut (rpmlib, GLIBC filtered):
    /bin/bash
    clevis-luks(x86-64)
    dracut-network
    nc

Provides
--------
clevis-debuginfo:
    clevis-debuginfo
    clevis-debuginfo(x86-64)

clevis-udisks2:
    clevis-udisks2
    clevis-udisks2(x86-64)

clevis-luks:
    clevis-luks
    clevis-luks(x86-64)

clevis:
    clevis
    clevis(x86-64)

clevis-dracut:
    clevis-dracut
    clevis-dracut(x86-64)

Package is APPROVED. Please fix the directory ownership issue when uploading.

Comment 15 Gwyn Ciesla 2016-11-18 18:30:27 UTC
Package request has been approved: https://admin.fedoraproject.org/pkgdb/package/rpms/clevis


Note You need to log in before you can comment on or make changes to this bug.