A remote code execution vulnerability in qmail
As a proof of concept, we developed a reliable, local and remote exploit against Debian's qmail package in its default configuration. This proof of concept requires 4GB of disk space and 8GB of memory, and allows an attacker to execute arbitrary shell commands as any user, except root (and a few system users who do not own their home directory)."
From: | Qualys Security Advisory <qsa-AT-qualys.com> | |
To: | oss-security-AT-lists.openwall.com | |
Subject: | [oss-security] Remote Code Execution in qmail (CVE-2005-1513) | |
Date: | Tue, 19 May 2020 10:05:06 -0700 | |
Message-ID: | <20200519170506.GC22032@localhost.localdomain> | |
Archive-link: | Article |
Qualys Security Advisory 15 years later: Remote Code Execution in qmail (CVE-2005-1513) ======================================================================== Contents ======================================================================== Summary Analysis Exploitation qmail-verify - CVE-2020-3811 - CVE-2020-3812 Mitigations Acknowledgments Patches ======================================================================== Summary ======================================================================== TLDR: In 2005, three vulnerabilities were discovered in qmail but were never fixed because they were believed to be unexploitable in a default installation. We recently re-discovered these vulnerabilities and were able to exploit one of them remotely in a default installation. ------------------------------------------------------------------------ In May 2005, Georgi Guninski published "64 bit qmail fun", three vulnerabilities in qmail (CVE-2005-1513, CVE-2005-1514, CVE-2005-1515): http://www.guninski.com/where_do_you_want_billg_to_go_tod... Surprisingly, we re-discovered these vulnerabilities during a recent qmail audit; they have never been fixed because, as stated by qmail's author Daniel J. Bernstein (in https://cr.yp.to/qmail/guarantee.html): "This claim is denied. Nobody gives gigabytes of memory to each qmail-smtpd process, so there is no problem with qmail's assumption that allocated array lengths fit comfortably into 32 bits." Indeed, the memory consumption of each qmail-smtpd process is severely limited by default (by qmail-smtpd's startup script); for example, on Debian 10 (the latest stable release), it is limited to roughly 7MB. Unfortunately, we discovered that these vulnerabilities also affect qmail-local, which is reachable remotely and is not memory-limited by default (we investigated many qmail packages, and *all* of them limit qmail-smtpd's memory, but *none* of them limits qmail-local's memory). As a proof of concept, we developed a reliable, local and remote exploit against Debian's qmail package in its default configuration. This proof of concept requires 4GB of disk space and 8GB of memory, and allows an attacker to execute arbitrary shell commands as any user, except root (and a few system users who do not own their home directory). We will publish our proof-of-concept exploit in the near future. About our new discovery, Daniel J. Bernstein issues the following statement: "https://cr.yp.to/qmail/guarantee.html has for many years mentioned qmail's assumption that allocated array lengths fit comfortably into 32 bits. I run each qmail service under softlimit -m12345678, and I recommend the same for other installations." Finally, we also discovered two minor vulnerabilities in qmail-verify (a third-party qmail patch that is included in, for example, Debian's qmail package): CVE-2020-3811 (a mail-address verification bypass), and CVE-2020-3812 (a local information disclosure). ======================================================================== Analysis ======================================================================== We decided to exploit Georgi Guninski's vulnerability "1. integer overflow in stralloc_readyplus" (CVE-2005-1513). There are, in fact, four potential integer overflows in stralloc_readyplus; three in the GEN_ALLOC_readyplus() macro (which generates the stralloc_readyplus() function), at line 21 (n += x->len), line 23 (x->a = base + n + ...), and line 24 (x->a * sizeof(type)): ------------------------------------------------------------------------ 17 #define GEN_ALLOC_readyplus(ta,type,field,len,a,i,n,x,base,ta_rplus) \ 18 int ta_rplus(x,n) register ta *x; register unsigned int n; \ 19 { register unsigned int i; \ 20 if (x->field) { \ 21 i = x->a; n += x->len; \ 22 if (n > i) { \ 23 x->a = base + n + (n >> 3); \ 24 if (alloc_re(&x->field,i * sizeof(type),x->a * sizeof(type))) return 1; \ 25 x->a = i; return 0; } \ 26 return 1; } \ 27 x->len = 0; \ 28 return !!(x->field = (type *) alloc((x->a = n) * sizeof(type))); } ------------------------------------------------------------------------ and, in theory, one integer overflow in the alloc() function itself (which is called by the alloc_re() function), at line 18: ------------------------------------------------------------------------ 14 /*@null@*//*@out@*/char *alloc(n) 15 unsigned int n; 16 { 17 char *x; 18 n = ALIGNMENT + n - (n & (ALIGNMENT - 1)); /* XXX: could overflow */ .. 20 x = malloc(n); .. 22 return x; 23 } ------------------------------------------------------------------------ In practice, the integer overflows at line 21 (in GEN_ALLOC_readyplus()) and line 18 (in alloc()) are very hard to trigger; and the one at line 24 (in GEN_ALLOC_readyplus()) is irrelevant to stralloc_readyplus's case (because type is char and sizeof(type) is therefore 1). On the other hand, the integer overflow at line 23 (in GEN_ALLOC_readyplus()) is easy to trigger, because the size x->a of the buffer is increased by one eighth every time it is re-allocated: we send a very large mail message that contains a very long header line (nearly 4GB), and this line triggers stralloc_readyplus's integer overflow while in the getln() function, which is called by the bouncexf() function, at the beginning of the qmail-local program. qmail-local is responsible for the local delivery of mail messages, and runs with the privileges of the local recipient (or qmail's "alias" user, if the local recipient is "root", for example). After the size of the buffer is overflowed (at line 23), the alloc_re() function is called (at line 24), but with n < m, where n is the size of the new buffer y, and m is the size of the old buffer x: ------------------------------------------------------------------------ 4 int alloc_re(x,m,n) 5 char **x; 6 unsigned int m; 7 unsigned int n; 8 { 9 char *y; 10 11 y = alloc(n); 12 if (!y) return 0; 13 byte_copy(y,m,*x); 14 alloc_free(*x); 15 *x = y; 16 return 1; 17 } ------------------------------------------------------------------------ In other words, we transformed stralloc_readyplus's integer overflow into an mmap-based buffer overflow at line 13 (byte_copy() is qmail's version of memcpy()): m is nearly 4GB (the length of our very long header line), but n is roughly 512MB (one eighth of m). ======================================================================== Exploitation ======================================================================== To survive this large buffer overflow, we carefully choose the number and lengths of the very first lines in our mail message (they crucially influence the sequence of buffer re-allocations that eventually lead to the integer and buffer overflows), and obtain the following mmap layout: -------|-------|-------------------------------------------------|------ XXXXXXX| y | x | libc -------|-------|-------------------------------------------------|------ | 512MB | 4GB | Consequently, we safely overflow the new buffer y, and overwrite the malloc header of the old buffer x, with the contents of our very long header line. To exploit this malloc-header corruption when free(x) is called (at line 14), we devised an unusual method that bypasses NX and ASLR, but does not work against a full-RELRO binary (but the qmail-local binary on Debian 10 is partial-RELRO only). This does not mean, however, that a full-RELRO binary is not exploitable: other methods may exist, the only limit to malloc exploitation is the imagination. First, we overwrite the prev_size and size fields of x's malloc header, we set its IS_MMAPPED bit to 1, and therefore enter the munmap_chunk() function in __libc_free() (where p is a pointer to x's malloc header): ------------------------------------------------------------------------ 2810 static void 2811 munmap_chunk (mchunkptr p) 2812 { 2813 INTERNAL_SIZE_T size = chunksize (p); .... 2822 uintptr_t block = (uintptr_t) p - prev_size (p); 2823 size_t total_size = prev_size (p) + size; .... 2838 __munmap ((char *) block, total_size); 2839 } ------------------------------------------------------------------------ Because we completely control the size field (at line 2813) and the prev_size field (at lines 2822 and 2823), we completely control the block address (relative to p, and hence x) and the total_size of the __munmap() call (at line 2838). In other words, we can munmap() an arbitrary mmap region, without knowing the ASLR; we munmap() roughly 576MB at the end of x, including the first few pages of the libc: -------|-------|-----------------------------------------|-------+-|---- XXXXXXX| y | x |XXXXXXXXX|ibc -------|-------|-----------------------------------------|-------+-|---- The first pages of the libc do not actually contain executable code: they contain the ELF .dynsym section, which associates a symbol (for example, the "open" function) with the address of this symbol (relative to the start of the libc). Next, we end our very long header line (with a '\n' character), and start a new header line of nearly 576MB. This new header line is first written to the buffer y, but when y is full, stralloc_readyplus() allocates a new buffer t of roughly 576MB (the size of y plus one eighth), the exact size of the mmap region that we previously munmap()ed: -------|-------|-----------------------------------------|-------+-|---- XXXXXXX| y | x | t |ibc -------|-------|-----------------------------------------|-------+-|---- Consequently, we completely control the first pages of the libc (they contain the end of our new header line): we control the .dynsym section, and we replace the address of the "open" function with the address of the "system" function. This method works because Debian's qmail-local binary is partial-RELRO only, and because the open() function has not been called yet, and has therefore not been resolved yet. Last, we end our new header line, and when qmail-local returns from bouncexf() and calls qmesearch() to open() the ".qmail-extension" file, system(".qmail-extension") is called instead. Because we control this "extension" (it is an extension of the local recipient's mail address, for example localuser-extension@localdomain), we can execute arbitrary shell commands as any user (except root, and a few system users who do not own their home directory), by sending our large mail message to "localuser-;command;@localdomain". Last-minute note: the exploitation of glibc's free() to munmap() arbitrary memory regions has been discussed before, in http://tukan.farm/2016/07/27/munmap-madness/. ======================================================================== qmail-verify ======================================================================== ------------------------------------------------------------------------ CVE-2020-3811 ------------------------------------------------------------------------ Although the original qmail-smtpd does accept our recipient address "localuser-;command;@localdomain", Debian's qmail-smtpd should not, because it validates the recipient address with an external program qmail-verify (which should reject our recipient address, because the file "~localuser/.qmail-;command;" does not exist). Unfortunately, qmail-verify does reject "localuser-;command;@localdomain", but it accepts the unqualified "localuser-;command;" (without the @localdomain), because: - it never calls the control_init() function; - it therefore initializes its default domain to the hard-coded string "envnoathost"; - and accepts any unqualified mail address as valid by default (because its default domain "envnoathost" is not one of qmail's local domains, and is therefore unverifiable). ------------------------------------------------------------------------ CVE-2020-3812 ------------------------------------------------------------------------ We also discovered a minor information disclosure in qmail-verify: a local attacker can test for the existence of files and directories anywhere in the filesystem (even in inaccessible directories), because qmail-verify runs as root and tests for the existence of files in the attacker's home directory, without dropping its privileges first. For example (qmail-verify listens on 127.0.0.1:11113 by default): ------------------------------------------------------------------------ $ ls -l /root/.bashrc ls: cannot access '/root/.bashrc': Permission denied $ rm -f ~john/.qmail-test $ ln -s /root/.bashrc ~john/.qmail-test $ echo -n 'john-test@localdomain' | nc -w 2 -u 127.0.0.1 11113 | hexdump -C 00000000 a0 6a 6f 68 6e 2d 74 65 73 74 |.john-test| ------------------------------------------------------------------------ The least significant bit of this response's first byte (a0) is 0: the file "/root/.bashrc" exists. ------------------------------------------------------------------------ $ ls -l /root/.abcdef ls: cannot access '/root/.abcdef': Permission denied $ rm -f ~john/.qmail-test $ ln -s /root/.abcdef ~john/.qmail-test $ echo -n 'john-test@localdomain' | nc -w 2 -u 127.0.0.1 11113 | hexdump -C 00000000 e1 6a 6f 68 6e 2d 74 65 73 74 |.john-test| ------------------------------------------------------------------------ The least significant bit of this response's first byte (e1) is 1: the file "/root/.abcdef" does not exist. ======================================================================== Mitigations ======================================================================== As recommended by Daniel J. Bernstein, qmail can be protected against all three 2005 CVEs by placing a low, configurable memory limit (a "softlimit") in the startup scripts of all qmail services. Alternatively: qmail can be protected against the RCE (Remote Code Execution) by configuring the file "control/databytes", which contains the maximum size of a mail message (this file does not exist by default, and qmail is therefore remotely exploitable in its default configuration). Unfortunately, this does not protect qmail against the LPE (Local Privilege Escalation), because the file "control/databytes" is used exclusively by qmail-smtpd. ======================================================================== Acknowledgments ======================================================================== We thank Andrew Richards, Alexander Peslyak, the members of distros@openwall, and the developers of notqmail for their hard work on this coordinated release. We also thank Daniel J. Bernstein, and Georgi Guninski. Finally, we thank Julien Barthelemy, Stephane Bellenger, and Jean-Paul Michel for their inspiring work. ======================================================================== Patches ======================================================================== We wrote a simple patch for Debian's qmail package (below) that fixes CVE-2020-3811 and CVE-2020-3812 in qmail-verify, and fixes all three 2005 CVEs in qmail (by hard-coding a safe, upper memory limit in the alloc() function). Alternatively: - an updated version of qmail-verify will be available at https://free.acrconsulting.co.uk/email/qmail-verify.html after the Coordinated Release Date; - the developers of notqmail (https://notqmail.org/) have written their own patches for the three 2005 CVEs and have started to systematically fix all integer overflows and signedness errors in qmail. ------------------------------------------------------------------------ diff -r -u netqmail_1.06-6/alloc.c netqmail_1.06-6+patches/alloc.c --- netqmail_1.06-6/alloc.c 1998-06-15 03:53:16.000000000 -0700 +++ netqmail_1.06-6+patches/alloc.c 2020-05-04 16:43:32.923310325 -0700 @@ -1,3 +1,4 @@ +#include <limits.h> #include "alloc.h" #include "error.h" extern char *malloc(); @@ -15,6 +16,10 @@ unsigned int n; { char *x; + if (n >= (INT_MAX >> 3)) { + errno = error_nomem; + return 0; + } n = ALIGNMENT + n - (n & (ALIGNMENT - 1)); /* XXX: could overflow */ if (n <= avail) { avail -= n; return space + avail; } x = malloc(n); diff -r -u netqmail_1.06-6/qmail-verify.c netqmail_1.06-6+patches/qmail-verify.c --- netqmail_1.06-6/qmail-verify.c 2020-05-02 09:02:51.954415101 -0700 +++ netqmail_1.06-6+patches/qmail-verify.c 2020-05-08 04:47:27.555539058 -0700 @@ -16,6 +16,8 @@ #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> +#include <limits.h> +#include <grp.h> #include <pwd.h> #include <sys/socket.h> #include <netinet/in.h> @@ -38,6 +40,7 @@ #include "ip.h" #include "qmail-verify.h" #include "errbits.h" +#include "scan.h" #define enew() { eout("qmail-verify: "); } #define GETPW_USERLEN 32 @@ -71,6 +74,7 @@ void die_comms() { enew(); eout("Misc. comms problem: exiting.\n"); eflush(); _exit(1); } void die_inuse() { enew(); eout("Port already in use: exiting.\n"); eflush(); _exit(1); } void die_socket() { enew(); eout("Error setting up socket: exiting.\n"); eflush(); _exit(1); } +void die_privs() { enew(); eout("Unable to drop/restore privileges: exiting.\n"); eflush(); _exit(1); } char *posstr(buf,status) char *buf; int status; @@ -207,10 +211,47 @@ return 0; } +static int stat_as(uid, gid, path, sbuf) +const uid_t uid; +const gid_t gid; +const char * const path; +struct stat * const sbuf; +{ + static gid_t groups[NGROUPS_MAX + 1]; + int ngroups = 0; + const gid_t saved_egid = getegid(); + const uid_t saved_euid = geteuid(); + int ret = -1; + + if (saved_euid == 0) { + ngroups = getgroups(sizeof(groups) / sizeof(groups[0]), groups); + if (ngroups < 0 || + setgroups(1, &gid) != 0 || + setegid(gid) != 0 || + seteuid(uid) != 0) { + die_privs(); + } + } + + ret = stat(path, sbuf); + + if (saved_euid == 0) { + if (seteuid(saved_euid) != 0 || + setegid(saved_egid) != 0 || + setgroups(ngroups, groups) != 0) { + die_privs(); + } + } + + return ret; +} + int verifyaddr(addr) char *addr; { char *homedir; + uid_t uid = -1; + gid_t gid = -1; /* static since they get re-used on each call to verifyaddr(). Note that they don't need resetting since initial use is always with stralloc_copys() except wildchars (reset with ...len=0 below). */ @@ -303,6 +344,7 @@ if (r == 1) { char *x; + unsigned long u; if (!stralloc_ready(&nughde,(unsigned int) dlen)) die_nomem(); nughde.len = dlen; if (cdb_bread(fd,nughde.s,nughde.len) == -1) die_cdb(); @@ -318,10 +360,14 @@ if (x == nughde.s + nughde.len) return allowaddr(addr,ADDR_OK|QVPOS3); ++x; /* skip uid */ + scan_ulong(x,&u); + uid = u; x += byte_chr(x,nughde.s + nughde.len - x,'\0'); if (x == nughde.s + nughde.len) return allowaddr(addr,ADDR_OK|QVPOS4); ++x; /* skip gid */ + scan_ulong(x,&u); + gid = u; x += byte_chr(x,nughde.s + nughde.len - x,'\0'); if (x == nughde.s + nughde.len) return allowaddr(addr,ADDR_OK|QVPOS5); ++x; @@ -360,6 +406,8 @@ if (!stralloc_copys(&nughde,pw->pw_dir)) die_nomem(); if (!stralloc_0(&nughde)) die_nomem(); homedir=nughde.s; + uid = pw->pw_uid; + gid = pw->pw_gid; got_nughde: @@ -380,7 +428,7 @@ if (!stralloc_cat(&qme,&safeext)) die_nomem(); if (!stralloc_0(&qme)) die_nomem(); /* e.g. homedir/.qmail-localpart */ - if (stat(qme.s,&st) == 0) return allowaddr(addr,ADDR_OK|QVPOS10); + if (stat_as(uid,gid,qme.s,&st) == 0) return allowaddr(addr,ADDR_OK|QVPOS10); if (errno != error_noent) { return stat_error(qme.s,errno, STATERR|QVPOS11); /* Maybe not running as root so access denied */ } @@ -394,7 +442,7 @@ if (!stralloc_cats(&qme,"default")) die_nomem(); if (!stralloc_0(&qme)) die_nomem(); /* e.g. homedir/.qmail-[xxx-]default */ - if (stat(qme.s,&st) == 0) { + if (stat_as(uid,gid,qme.s,&st) == 0) { /* if it's ~alias/.qmail-default, optionally check aliases.cdb */ if (!i && (quser == auto_usera)) { char *s; @@ -423,6 +471,7 @@ char *s; if (chdir(auto_qmail) == -1) die_control(); + if (control_init() == -1) die_control(); if (control_rldef(&envnoathost,"control/envnoathost",1,"envnoathost") != 1) die_control(); [https://d1dejaj6dcqv24.cloudfront.net/asset/image/email-b...> This message may contain confidential and privileged information. If it has been sent to you in error, please reply to advise the sender of the error and then immediately delete it. If you are not the intended recipient, do not read, copy, disclose or otherwise use this message. The sender disclaims any liability for such unauthorized use. NOTE that all incoming emails sent to Qualys email accounts will be archived and may be scanned by us and/or by external service providers to detect and prevent threats to our systems, investigate illegal or inappropriate behavior, and/or eliminate unsolicited promotional emails (“spam”). If you have any concerns about this process, please contact us.
Posted May 20, 2020 19:53 UTC (Wed)
by jafd (subscriber, #129642)
[Link] (27 responses)
Posted May 20, 2020 20:14 UTC (Wed)
by mattrose (guest, #19610)
[Link] (26 responses)
Posted May 20, 2020 20:51 UTC (Wed)
by jafd (subscriber, #129642)
[Link] (24 responses)
I think there is something about OSS maintainership which attracts people like this.
Posted May 20, 2020 21:13 UTC (Wed)
by warrax (subscriber, #103205)
[Link] (2 responses)
Whoa, whoa, whoa... that's a hell of a leap.
Consider how much FOSS software you're using right now and how many of the maintainers of that software behave like DJB, or the maintainer(s) you're talking about.
Posted May 20, 2020 22:14 UTC (Wed)
by jafd (subscriber, #129642)
[Link]
It's not so much about the quantity. In case of Pango, it's now used almost everywhere a program wants to put some text on the screen.
Remember Ulrich Drepper in his infamous glibc days? glibc is only one piece, one may argue, but it's a kind of piece all other pieces depend on. And so on.
Posted May 21, 2020 0:43 UTC (Thu)
by lkundrak (subscriber, #43452)
[Link]
Posted May 20, 2020 21:19 UTC (Wed)
by Vipketsh (guest, #134480)
[Link] (4 responses)
It would be very good if people realise that everyone in this game of OSS is connected and depending on each other. Doubly so for core libraries, like your Pango example. Even seemingly unrelated components like for example a compiler and text editor at the end of the day depend on each other: the text editor breaks the compiler writers work flow and there may not be a compiler to compile said editor.
Posted May 20, 2020 22:27 UTC (Wed)
by jafd (subscriber, #129642)
[Link] (3 responses)
1. Take a project which many depend on but no one wants to touch with a barge pole (code issues, author died 20 years ago).
No one denies there's a lot of hard work involved, but this doesn't mean you're now ascended to infallibility or that it's always "your way or highway". Break a workflow of enough people, and there will appear bright individuals who not only are talking about replacing your work, but possess the actual capability to do so.
Posted May 21, 2020 2:49 UTC (Thu)
by NYKevin (subscriber, #129325)
[Link] (2 responses)
There is always an impedance mismatch between the users of the software and the developers. There is often a further impedance mismatch between power users and all other users, but let's ignore that for the sake of simplicity. For developers, maintainability is a Big Deal. Avoiding regressions is important, but sometimes, old code can be sufficiently convoluted or messy as to present an actual hazard to the long-term viability of the project. This may be because nobody understands how it works, because it is written in a non-extensible fashion, or because it's a pile of ugly hacks, but whatever the reason, it inevitably becomes a question of time and effort: How difficult will it be to exactly replicate the behavior of this bad code with good code? How strongly do we care about supporting this use case? How do those two concerns balance against each other?
But from the users' perspective, this is all invisible. All they can see is "It used to work, now it doesn't, why did you give me a pony then shoot it?" Of course, the average(!) user does not care that there is an actual answer to that question, because the average(!) user is not in a position to understand said answer anyway. Really, they either want to convince the developers to change their minds, or they just want to vent. The problem is that developer time is not infinitely fungible, especially in an OSS context. If literally no one wants to work on replacing the bad code with good code, then a replacement will not happen. In the meantime, other work is blocked on the bad code's continued existence. So what the user is really asking for is the project's cessation, which the developers obviously regard as unreasonable. In bad cases, developers and users will then proceed to talk past each other and get into huge flame wars on the project's mailing list, accomplishing exactly nothing.
(This is also where the second impedance mismatch comes in: Developers often choose to prioritize the needs of the many over the needs of the few, but in practice, power users are "the few." So they get frustrated when developers kill their prized feature in favor of supporting something more basic: https://xkcd.com/619/)
Instead, I think it's more helpful to focus on the respect with which users and developers treat one another. If the developers take a conciliatory "We're sorry this breaks your workflow, here are our suggested workarounds" attitude, users are likely to be a lot more accepting than if developers say "Your workflow is bad and you should feel bad." A little bit of compassion goes a very long way, even if it makes no difference in the actual software as-shipped.
Posted May 21, 2020 9:18 UTC (Thu)
by mgedmin (subscriber, #34497)
[Link]
Posted May 22, 2020 2:23 UTC (Fri)
by intelfx (subscriber, #130118)
[Link]
TBH that comic shows a literal inverse of your point.
Posted May 20, 2020 22:16 UTC (Wed)
by Sesse (subscriber, #53779)
[Link] (2 responses)
(Quick summary of the situation as I understand it: When “full hinting” is on, aka interpreting and executing the manual hint bytecode in the TTF file, the font metrics change. HarfBuzz used to depend on unmaintained code to get this right, but eventually found that too hard and not worth it over time, especially given that full hinting is only used by a (vocal!) minority of users and is useless on high-DPI monitors. So if you have it enabled in FreeType, HarfBuzz will believe that your glyph takes up N pixels and FreeType will render it using M pixels, and your text gets misaligned on screen because the next thing to render starts the wrong place.)
Posted May 20, 2020 22:57 UTC (Wed)
by jafd (subscriber, #129642)
[Link] (1 responses)
It would hold if the discussion was about a feature which didn't exist and would need to be implemented. In this case, it pretty much existed for more than a decade, and now suddenly this.
> So if you have it enabled in FreeType, HarfBuzz will believe that your glyph takes up N pixels and FreeType will render it using M pixels, and your text gets misaligned on screen because the next thing to render starts the wrong place.
Then the bug is that configurations that make this situation possible are not processed properly. Make whatever sets those two libraries up cater to the lowest common denominator (full hinting -> medium, or what maximum Harfbuzz can use) so there's never ever a mismatch, and be done with it. Explaining why hinting cannot be cranked up to full anymore is IMO way easier than explaining why the text is suddenly drunken and unreadable.
But why do it, when we can fuel the drama up with arrogant remarks.
> useless on high-DPI monitors
On your typical office PCs, HiDPI monitors, alas, are still a minority. And as people age, they seem to want unreasonable things like more contrast text; I keep wondering, why would they.
Posted May 21, 2020 12:07 UTC (Thu)
by Sesse (subscriber, #53779)
[Link]
And I agree, one should probably just remove the setting for full hinting.
Posted May 20, 2020 22:18 UTC (Wed)
by joib (subscriber, #8541)
[Link] (12 responses)
The Harfbuzz maintainer seems tired of people who disagree about the development priorities, have time for endless hyperbolic discussions about the one true way their favourite font should be rendered on their particular system with their particular (very much non default) config, yet somehow don't have time to contribute in any manner.
Posted May 20, 2020 22:47 UTC (Wed)
by jafd (subscriber, #129642)
[Link] (11 responses)
Telling "we're not going back to the old behaviour because so and so" can at least tell where the decision is coming from. Telling "we're sorry it's going to break some setups which have such and such settings" at least acknowledges that there are problems. Telling to "use something else, it's Free Software" or "go buy yourself a HiDPI monitor" is straight away toxic.
It's also not like the maintainer is volunteering for free.
My personal setup was not affected by that issue. But tell you what, I wouldn't tolerate an individual with such attitude on my team, even if he held two Nobel prizes, four Oscars, and was willing to work for peanuts.
> have time for endless hyperbolic discussions about the one true way their favourite font should be rendered on their particular system with their particular (very much non default) config, yet somehow don't have time to contribute in any manner.
In other words, if you're not a better programmer than the author, you're little people and your feedback is of no consequence. It's almost like telling that you cannot say the restaurant food is foul because you're not a chef yourself and don't work in the same kitchen.
Posted May 21, 2020 7:37 UTC (Thu)
by joib (subscriber, #8541)
[Link] (1 responses)
It's clearly a regression if it's an unintended change. If dropping support for feature X is on the roadmap (for whatever reasons) then, well, not so clear anymore.
> Telling "we're not going back to the old behaviour because so and so" can at least tell where the decision is coming from. Telling "we're sorry it's going to break some setups which have such and such settings" at least acknowledges that there are problems.
Seems that in this case the maintainer(s) have quite clearly communicated what the path forward is, taking into account their priorities and available resources.
Disagreeing on the roadmap is fine, of course. But ultimately it boils down to
1. DIY.
Needless to say, throwing bile at the maintainers is unlikely to be a successful strategy for #3. Of course, maintainers should keep their cool and not be provoked (which, to an extent seems to have failed here), but OTOH maintainers, even ones who are employed by big evil soulless corporations, are humans too.
> In other words, if you're not a better programmer than the author, you're little people and your feedback is of no consequence.
Of course not. I'm sure all projects warmly welcome respectful feedback. Throwing tantrums and harassing maintainers is, OTOH, not likely to be a productive approach to getting what you want.
> It's almost like telling that you cannot say the restaurant food is foul because you're not a chef yourself and don't work in the same kitchen.
This case seems more to be like the customer going to the restaurant kitchen yelling that before the current owner took over and remodeled the place to be this posh restaurant, this used to be Old Joe's Biker Bar and they served proper food. And then they just continue yelling and won't leave until the owner threatens to call the police.
Posted May 21, 2020 20:43 UTC (Thu)
by gerdesj (subscriber, #5446)
[Link]
A few years ago *cough*, I wanted 802.1Q VLAN support in Linux but it seemed to be taking a while for some bloke called Ben to get it all sorted out. I sent an email asking what help I could provide. Testing was the reply with patches attached. The first effort failed to compile and a short to and fro got it up and running enough for mainline.
My test Compaq box got its 10 VLANs on one NIC. I wrote a script to create 10 x 15 smb.conf files to create the master browser from hell! 15 workgroup names ...
Posted May 22, 2020 0:06 UTC (Fri)
by HelloWorld (guest, #56129)
[Link] (8 responses)
> It's almost like telling that you cannot say the restaurant food is foul because you're not a chef yourself and don't work in the same kitchen.
Posted May 22, 2020 1:45 UTC (Fri)
by pizza (subscriber, #46)
[Link]
The term for that sort of person is a "choosing beggar", made popular by the /r/ChoosingBeggars sub-reddit.
Posted May 22, 2020 12:06 UTC (Fri)
by Vipketsh (guest, #134480)
[Link] (2 responses)
It also needs to be understood somewhere that replacing core components and then maintaining that replacement just for yourself is a HUGE amount of work, if possibly by yourself only. Thus being told by some maintainer of a core piece "go replace it yourself" is little more than being given the middle finger and being told "junk yard dogs not welcome here".
Posted May 22, 2020 12:35 UTC (Fri)
by Wol (subscriber, #4433)
[Link]
The problem, all too often, is that you need a piece of functionailty, and the maintainer has no time/interest in doing it. Plus the maintainer also needs to eat ...
If I were a maintainer, I'd have no qualms about saying "you want it, you pay for it". You just need mutual respect - the user needs the functionality, the maintainer needs food etc, how do we work out something that's beneficial to both ... ?
Cheers,
Posted May 22, 2020 21:36 UTC (Fri)
by HelloWorld (guest, #56129)
[Link]
> It also needs to be understood somewhere that replacing core components and then maintaining that replacement just for yourself is a HUGE amount of work, if possibly by yourself only.
Posted May 26, 2020 3:28 UTC (Tue)
by ssmith32 (subscriber, #72404)
[Link] (3 responses)
If you've accepted the work they put into bug reports, and leveraged the work they put into marketing your software for your own benefit, and then turned around and made a comment like this, you may be making a rational comment, but you may also be an ungrateful jerk & a bad maintainer. But if you say *why you don't want to do it a certain way (in a clear and technical way, devoid of figurative language) and suggest alternatives, then you may not be a jerk. Context & empathy matter. Even if the reason is "this feature is too much work to maintain" - that's fine.
> more appropriate comparison would be a beggar who is given some free food and who then complains because it's just a slice of pizza rather than caviar and champagne.
And if the homeless person had started sweeping your sidewalk, and greeting your customers in a charming & friendly fashion, and you decide to give them a rotten pickle from the trash, instead of pizza one day, you'd be a jerk then too. If you gave them a turkey sandwich, and they throw it at you, not so much.
In short, in many open source projects, the line between "user" and "contributor" is not clear cut.
And if you think of your users like beggars, you shouldn't be a maintainer. Open Source would be better off without your software - leave space for someone else who actually wants to create something useful for other people, and cares about their users.
Even Linus, at the peak of his infatuation with metaphorical (vs dry, technical) descriptions of issues, always valued the end user. Harsh on other maintainers, yes, but genuinely worked to solve user's issues ( no user space regressions! ).
If you're not in it to help your users, get out. But sometimes, you do have to set boundaries & clear expectations. Again, context & empathy matter.
>As a user, you simply don't get to decide how a project is developed, that's simply the way it works.
And they'll fork your software, rename it, and have no obligation to give you credit, outside of brief mentions in particular license text. If you're gonna be a condescending jerk, expect the world to return the favor. That's simply the way it works.
Posted May 26, 2020 23:40 UTC (Tue)
by HelloWorld (guest, #56129)
[Link] (2 responses)
So in your opinion somebody who has poured hundreds or thousands of hours into an open source project is supposed to be eternally grateful because somebody came along and took half an hour to write a bug report, and who probably didn't do so out of the kindness of their heart but because they just wanted it fixed? Give me a break. It's exactly the other way around: when somebody gets free bugfixes, they're the ones who should be grateful. The simple fact is that most open source projects are built by a tiny number of contributors who do the vast majority of the work. And it couldn't possibly be any other way, for the simple reason that developing software requires a software stack much bigger than any single developer could hope to develop in a lifetime.
> And if the homeless person had started sweeping your sidewalk, and greeting your customers in a charming & friendly fashion, and you decide to give them a rotten pickle from the trash, instead of pizza one day, you'd be a jerk then too.
> And if you think of your users like beggars, you shouldn't be a maintainer.
> If you're not in it to help your users, get out.
> And they'll fork your software, rename it, and have no obligation to give you credit,
Posted May 27, 2020 1:17 UTC (Wed)
by pizza (subscriber, #46)
[Link]
30 minutes is two order of magnitude more effort than goes into the typical bug report.
Posted May 27, 2020 4:15 UTC (Wed)
by flussence (guest, #85566)
[Link]
When you reduce the worth someone's presence adds to something as black-and-white as the dollar/labour value they contribute to a thing, I can see why you'd make that mistake.
Apache OpenOffice feels they're important because they have millions of users. Perhaps you can go convince them they're wrong.
Posted May 20, 2020 21:09 UTC (Wed)
by warrax (subscriber, #103205)
[Link]
Posted May 22, 2020 18:31 UTC (Fri)
by bib (guest, #114736)
[Link] (3 responses)
xorg - Forcing 75dpi by default rather than native dpi, such as 109 on my setup. This has now helped break chrome.
KDE - Moving borders of full screen windows off monitor. This screws up those with multiple monitors,since the border from an app on one screen, now appears on the neighbouring screen.
Why do devs insist on breaking things 'cause it works for them?, rather than doing it properly?
Posted May 25, 2020 22:16 UTC (Mon)
by shane (subscriber, #3335)
[Link] (2 responses)
Is your concern about borders of full screen applications appearing on other monitors a new behavior? Otherwise, maybe it was fixed and the KDE developers do give a rat's ass? ¯\_(ツ)_/¯
Posted May 25, 2020 22:41 UTC (Mon)
by pizza (subscriber, #46)
[Link] (1 responses)
This worked just fine on my last laptop. Did it at least twice a day, both while suspended and with hot-plugging. I used it for five years, and it ran Fedora + Gnome3 the entire time.
So there's probably some hardware/kernel/driver-level interaction going on. Still plenty of those bugs to go around, alas.
Posted May 26, 2020 10:54 UTC (Tue)
by mgedmin (subscriber, #34497)
[Link]
A remote code execution vulnerability in qmail
A remote code execution vulnerability in qmail
A remote code execution vulnerability in qmail
A remote code execution vulnerability in qmail
A remote code execution vulnerability in qmail
A remote code execution vulnerability in qmail
A remote code execution vulnerability in qmail
A remote code execution vulnerability in qmail
2. Claim maintainership, do a lot of hard work on it no one would question was long overdue.
3. Claim you're now the saviour of Linux on desktop or somesuch like that (X for humans?), because no one wanted to maintain it and you stepped in.
4. Make sure there's enough marketing so alternatives just die out.
5. For the best results, collect paycheck from Red Hat/IBM or Microsoft.
6. Tell any people who had regressions because of your decisions to GTFO because you're the martyr doing the thankless job, and they are little people.
A remote code execution vulnerability in qmail
A remote code execution vulnerability in qmail
A remote code execution vulnerability in qmail
A remote code execution vulnerability in qmail
A remote code execution vulnerability in qmail
A remote code execution vulnerability in qmail
A remote code execution vulnerability in qmail
A remote code execution vulnerability in qmail
A remote code execution vulnerability in qmail
2. Pay someone else to do it.
3. Convince the maintainers to do it.
4. Get used to the new way of doing things and move on.
A remote code execution vulnerability in qmail
A remote code execution vulnerability in qmail
Yes, exactly. As a user, you simply don't get to decide how a project is developed, that's simply the way it works. Telling people to use something else if they don't like it is a perfectly reasonable thing to say.
You do realize that you pay for the food in a restaurant, right? A more appropriate comparison would be a beggar who is given some free food and who then complains because it's just a slice of pizza rather than caviar and champagne.
A remote code execution vulnerability in qmail
A remote code execution vulnerability in qmail
A remote code execution vulnerability in qmail
Wol
A remote code execution vulnerability in qmail
When something is open source, you get to use it whether or not you've previously contributed to it, or to any other open source project. Calling that a “barter” is just a misuse of the word.
If you want a project to implement some feature, and you can't do it yourself or pay somebody to do it, well, tough cookies. You're simply not entitled to getting software development work done for free. As an open source user, you don't have any rights other than those that the license grants you, period. It really is that simple.
A remote code execution vulnerability in qmail
A remote code execution vulnerability in qmail
If I ran a business and wanted somebody to sweep the sidewalk or greet my customers, I'd hire somebody to do it. The last thing I'd want is homeless people loitering in front of my business.
The simple fact of the matter is that most users are *not* contributors. They're using the software and they never wrote a single line of code for it. Receiving something for nothing, how is that different from being a beggar?
I've contributed many bug fixes and enhancements to various open source projects, and you know what? I couldn't care less if that helped anybody else. I did it because I'm using those projects, and contributing fixes upstream is the easiest way to get somebody else to maintain that code in the future.
You do realize that that is exactly what an open source license allows them to do, right? If a maintainer has a problem with that, then why the f*ck would they place their code under an open source license in the first place? You're just not making any sense.
A remote code execution vulnerability in qmail
A remote code execution vulnerability in qmail
A remote code execution vulnerability in qmail
A remote code execution vulnerability in qmail
KDE full screen borders with multiple monitors
KDE full screen borders with multiple monitors
KDE full screen borders with multiple monitors