Study this 38 and 85 lines of sctd.sh and sct.c to see if it is (or make it) safe to be used in dom0 - A solution to the much-code Redshift used by many Qubes users

Basically, I needed Night Light Filter.
Searched on Qubes places, and found only Redshift.

Installing anything in dom0 is not recommended.
Thus, I posted two posts:

Understanding security implications of running Redshift -or similar software- in dom0

Is there a way to Night Light Filter or Grayscale without installing anything in dom0

(The forum doesn’t allow me to put more than two links, so I can’t put links of posts.)

In the second post, a software called sct was mentioned by solene. Thanks to her.

I am no cybersecurity expert when it comes to code, thus I’m asking for studying this very small code.
I think it’ll be amazing if it was studied and vulnerabilities were cleaned, as I see that Redshift (used by many Qubes users) is much code, that may be not as safe to run in dom0. Isn’t that right? Please let me know! Because I think if Redshift is safe to run in dom0, then there’s no reason to study this.

There is the code. Source: https://www.umaxx.net/dl/sct-0.5.tar.gz. The archive contains:

  • Makefile
  • README
  • sct.1 (a man page)
  • sctd.1 (a man page)
  • sctd.sh
  • sct.c.

I think only sctd.sh and sct.c are needed.


schd.sh:

#!/bin/sh

readonly S_V="0.5" S_YR="2017-2020"

s_err() {
    logger -i -p daemon.err -s -t "sctd" "error: ${1}"; exit 1
}

s_hm() {
    local h m
    h=$(date +"%H" | sed -e 's/^0//') || s_err "hours failed"
    m=$(date +"%M" | sed -e 's/^0//') || s_err "minutes failed"
    printf "$((h*60 + m))\n"
}

s_run() {
    local r hm=$(s_hm) inc=2 t=${1:-4500} sct=$(which sct) || s_err "sct not found"
    [ $hm -gt 720 ] && { t=$((t + inc * (1440 - hm))); } ||
                       { t=$((t + inc * hm)); }
    while :; do
        hm=$(s_hm)
        [ $hm -gt 720 ] && { t=$((t - inc)); } || { t=$((t + inc)); }
        r=$(${sct} ${t})
        [ $? -eq 0 ] && { logger -i -p daemon.info -s -t "sctd" "${r}"; } ||
                        { s_err "${r}"; }
        sleep 60
    done
}

s_main() {
    [ $# -eq 1 ] && [ "${1}" = "version" ] &&
        { printf "sctd %s (c) %s Aaron Bieber, Joerg Jung\n" ${S_V} ${S_YR};
          exit 0; }
    [ $# -gt 1 ] &&
        { printf "usage: sctd [<temp>]\n%7ssctd version\n" " ";
          exit 1; }
    [ $# -eq 1 ] && 
        { [ -z "${1##*[!0-9]*}" -o "${1}" -lt 2000 -o "${1}" -gt 9000 ] && 
          s_err "temp failed"; }
    trap "s_err \"signal received\"" 1 2 3 13 15
    s_run "$@"
}

s_main "$@"

sct.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <err.h>
#include <errno.h>
#include <limits.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xproto.h>
#include <X11/Xatom.h>
#include <X11/extensions/Xrandr.h>

#define S_V "0.5"
#define S_YR "2015-2020"

enum { S_RED, S_GREEN, S_BLUE, S_MAX };

static const float s_wp[][S_MAX] = { /* whitepoint values from redshift */
    { 1.00000000, 0.18172716, 0.00000000 }, /* 1000K */
    { 1.00000000, 0.42322816, 0.00000000 },
    { 1.00000000, 0.54360078, 0.08679949 },
    { 1.00000000, 0.64373109, 0.28819679 },
    { 1.00000000, 0.71976951, 0.42860152 },
    { 1.00000000, 0.77987699, 0.54642268 },
    { 1.00000000, 0.82854786, 0.64816570 },
    { 1.00000000, 0.86860704, 0.73688797 },
    { 1.00000000, 0.90198230, 0.81465502 },
    { 1.00000000, 0.93853986, 0.88130458 },
    { 1.00000000, 0.97107439, 0.94305985 },
    { 1.00000000, 1.00000000, 1.00000000 }, /* 6500K */
    { 0.95160805, 0.96983355, 1.00000000 },
    { 0.91194747, 0.94470005, 1.00000000 },
    { 0.87906581, 0.92357340, 1.00000000 },
    { 0.85139976, 0.90559011, 1.00000000 },
    { 0.82782969, 0.89011714, 1.00000000 },
    { 0.80753191, 0.87667891, 1.00000000 },
    { 0.78988728, 0.86491137, 1.00000000 }, /* 10000K */
    { 0.77442176, 0.85453121, 1.00000000 } };

static double s_avg(int t, double r, int c) {
    return s_wp[t / 500][c] * (1 - r) + s_wp[t / 500 + 1][c] * r;
}

#define S_YELLOW "\x1b[93m"
#define S_RST "\x1b[0m"

static void s_run(const char *s) {
    Display *d;
    XRRScreenResources *sr = NULL;
    XRRCrtcGamma *cg;
    unsigned long t;
    double r, g;
    int i, j, sz;
    char *e;

    errno = 0, t = strtoul(s, &e, 10);
    if (s[0] == '\0' || *e != '\0' || (errno == ERANGE && t == ULONG_MAX))
        errx(1, "temp failed");
    if (t < 1000 || t > 10000)
        t = 6500, warnx("temp range");
    t -= 1000, r = t % 500 / 500.0;
    if (!(d = XOpenDisplay(NULL)) || !(sr = XRRGetScreenResourcesCurrent(d,
        RootWindow(d, DefaultScreen(d)))))
        err(1, "XOpenDisplay or XRRGetScreenResourcesCurrent failed");
    for (i = 0; i < sr->ncrtc; i++) {
        sz = XRRGetCrtcGammaSize(d, sr->crtcs[i]);
        if (!(cg = XRRAllocGamma(sz)))
            err(1, "XRRAllocGamma failed");
        for (j = 0; j < sz; j++) {
            g = 65535.0 * j / sz;
            cg->red[j] = g * s_avg(t, r, S_RED);
            cg->green[j] = g * s_avg(t, r, S_GREEN);
            cg->blue[j] = g * s_avg(t, r, S_BLUE);
        }
        XRRSetCrtcGamma(d, sr->crtcs[i], cg);
        XFree(cg);
    }
    printf(isatty(fileno(stdout)) ? S_YELLOW "Temperature: %luK" S_RST "\n" :
        "Temperature: %luK\n", t + 1000);
    XFree(sr), XCloseDisplay(d);
}

int main(int argc, char *argv[]) {
    if (argc == 2 && !strcmp(argv[1], "version")) {
        puts("sct "S_V" (c) "S_YR" Ted Unangst, Joerg Jung");
        return 0;
    }
    if (argc > 2)
        errx(1, "usage: sct [<temp>]\n%12ssct version", "");
    s_run((argc == 2) ? argv[1] : "6500");
    return 0;
}

It does really nothing more than modifying Xorg color. The script will log color changes or errors if any.

Now, you will need to compile it, are you going to review the compiler as well? :smiley: Ideally, you can compile it in an offline qube and move the produced binary into dom0. Or you can install the compiler in dom0 (maybe gcc is already there?), but it is not really seen as best practice.

3 Likes

I don’t know why I’m feeling you not so serious about security, or am I who miss something? Please consider my threat model to be high. Basically I say: how are thing that: “do nothing more than X and Y” end up being exploited and their system compromised? Or is it because of other malicious things being added to the system that exploit them? And since dom0 gets nothing added to it it’s safe (is it… 100% safe?)


I have a question: Since it does nothing more than modifying Xorg colors, doesn’t that mean that I can do that manually with Xorg commands (and this sct tool just exists for making me don’t do it manually)? Like, what is special in this tool? It doesn’t install anything and it didn’t say it needs dependencies. Doesn’t that mean that it just executes or uses some already existing commands on the system that I execute or use as well?

If no, and this tool does whatever special I can’t do for some reason (please explain why), then what is the most safe way to have it working in dom0?

I can think of: Start whonix-workstation-17-dvm disposable terminal and only run ‘sudo apt install wget’ then ‘wget URL_OF_SCT’ then very well verify it (like with GPG, and use another Tor Browser disp to see the fingerprint and compare). Then afer verification send the sct files to an offline qube to be compiled there. And here, is there a compiler in a minimal template (if no, what is the absolute, absolute minimal compiler I can do this job with? so I can create another template and install only that on.) Then we compile, and send the binary to dom0.

I’m thinking of problems here: The whonix-workstation-17-dvm disposable of terminal that we used to install wget and download and verify sct, is networked, which means that it should be considered compromised, right? (like, an attacker just reaches this VM from the internet and attack like sys-whonix and sys-firewall or so and eventually be able to compromise the VM)? Then, copying from that disp to eventually dom0 is game over! Because even copying and pasting using the clipboard (copy those few lines of sh and c files to the offline Qube that is absolute clean as it’s based on an unmodified minimal template with only one apt install command run in it to install an absolute minimal compiler), which is the most safe way I can think of, still introduces security issues as the VM of whonix-workstation-17-dvm disp is considered compromised and thus the hacker can simply fake the clipboard contents with some 0-days that exploit whatever bug in the very clean offline VM made only for the compiler, which then allows them to make the compiler compile a bad thing that when goes to dom0 it will be game over.

Is this BS? Please tell me, as I use to think this way so much.

Thanks in advance.

If your threat model is that high, you should not trust a security audit done for free from a stranger

I don’t think sct can be used for an exploit because it does not much thing that a local attacker could do without sct.

The real risk is to have a program containing a rogue function that is not yet known, or that it has a SUID bit set (allowing it to run as root without being root) and which would have a vulnerability.

sct uses Xorg library to manipulate xorg. There is no utility to do it “manually”, except sct which allows you to do “manually”, unfortunately it is not provided along with Xorg tools as it is an independent project.

I can’t really say this is complete bullshit, but you need to trust something at some point if you want to use your computer.

For instance, if you consider that programs packages by the fedora team are safe, this would allow you to:

  • install redshift in dom0
  • or install a compiler in a fedora template, create qube from that template, compile sct to a binary, move that binary to dom0

You already trust the Fedora developers because it is the operating system that runs dom0, the people writing Xen and the Qubes OS team (not even considering all the people involved into Xorg, XFCE, GCC, Python, Perl, Make, Ruby, LLVM, librsvg etc…).

1 Like

There is also a big difference between expecting that redshift could be buggy or malicious. The former is relatively likely, but nobody should be able to use its vulnerability in dom0 to do harm. The latter is much less likely, especially since it has to target Qubes OS specifically.