LWN.net Weekly Edition for November 17, 2016
A discussion on GPL compliance
Among its many activities, the Software Freedom Conservancy (SFC) is one of the few organizations that does any work on enforcing the GPL when other compliance efforts have failed. A suggestion by SFC executive director Karen Sandler to have a Q&A session about compliance and enforcement at this year's Kernel Summit led to a prolonged discussion, but not to such a session being added to the agenda. However, the co-located Linux Plumbers Conference set up a "birds of a feather" (BoF) session so that interested developers could hear more about the SFC's efforts, get their questions answered, and provide feedback. Sandler and SFC director of strategic initiatives Brett Smith hosted the discussion, which was quite well-attended—roughly 70 people were there at a 6pm BoF on November 3.
Sandler started by noting that she is passionate about free software in part because she has a heart defibrillator implanted in her body, but has no access to the software running there. Smith recently joined SFC after stints with the Free Software Foundation as a license compliance engineer and as a system administrator at the World Wide Web Consortium (W3C). The SFC currently has 40 projects under its umbrella, for which it handles various administrative tasks, but the organization also runs the GPL compliance project for Linux kernel developers, which was the topic for the session.
Sandler laid out the ground rules for the discussion: no recordings and to ask
people before quoting them (which we have followed here). As is generally
the case, those who spoke up
are not representing the company they work for, but were speaking for
themselves. And, of course, Sandler is a lawyer, but was not giving any
legal advice ("iaal, but tinla, ianyl
" from her slides).
The only current legal action that the SFC is involved with is Christoph Hellwig's GPL enforcement suit against VMware, which was filed in 2015 and dismissed back in August—though Hellwig is appealing. The SFC is funding the suit as part of its GPL compliance project. Hellwig spoke up to say that he was particularly interested in hearing the opinions of those in the room who are not part of the SFC GPL compliance project.
Sandler noted that the SFC had just released copies of the template agreements for developers who join the compliance project, either anonymously [PDF] or under their own name [PDF]. That is an effort to be more transparent about the project, which is, as with all GPL enforcement efforts undertaken by the SFC and others, done under "The Principles of Community-Oriented GPL Enforcement". That document makes it clear that the goal is for GPL compliance and that legal action is a last resort. That document is "codifying our gentle approach" to enforcement, she said.
McHardy suits
She asked the room who had heard of Patrick McHardy and the GPL-enforcement lawsuits in Germany. Those suits appear to be well outside community expectations of how enforcement should be done (as well as running afoul of the Principles). Most in the room seemed to have heard of the suits, so Sandler did not give an introduction to all of that.
An audience member asked why it is that people have such a negative view of enforcement. Sandler said there is lots of confusion out there about lawsuits; they also tend to make people skittish. One key thing to remember is that today's violators are tomorrow's contributors, which is something that it is rare for companies to acknowledge—Samsung has been comfortable talking about that transition, but few others are. There is also a lot of "fear, uncertainty, and doubt" (FUD) about lawsuits, which muddies the waters. The Principles are meant to help with that by bringing clarity so that companies and others know what to expect with respect to GPL enforcement.
Lawsuits have a cost, in terms of time, money, opportunity, and other things, Smith said. It is natural for some in the community to question whether a particular suit was worth it, which can also lead some to have a negative view of enforcement actions.
But the McHardy suits are entirely different; James Bottomley called them a "generic shakedown". It means that there is a "copyright troll" in the community who is extracting a "couple of hundred thousand euros" in settlements from companies, he said. The existence of that troll makes companies have the mindset that the GPL is bad, he said. It makes for a "nasty environment" where companies will tar and feather anyone launching lawsuits because they associate them with the McHardy shakedown.
Grant Likely noted that there is more to the GPL than simply a license; it is a value statement as well. Using the GPL says that a project values collaboration and openness; it is both a social document and a legal document. Likely said that stressing that to companies helps when talking to them about the GPL.
Hellwig said that he preferred to refer to his suit as a copyright action, rather than a GPL-enforcement action. In the end, that is what it is and copyright lawsuits happen all the time in industry. But if the Linux community uses that same tool, suddenly it becomes a big problem.
The Linux community has been so lax in its enforcement of the GPL that it has made it much easier for McHardy to find targets, David Woodhouse said. If the community had pushed harder for compliance and done more enforcement, those companies would have been in compliance, which would have left McHardy with fewer (or no) companies to go after. Though Tim Bird pointed out that more enforcement may have led to fewer kernel contributors; that was one point that Linus Torvalds was making in the long ksummit-discuss thread, Bird said.
BusyBox is often brought up as an example of a community that was "killed" by the GPL enforcement done on its behalf, Laura Abbott said. It is a common complaint, she said, but is it true? Sandler said that it was an exaggeration, but that the BusyBox community "took a hit" for its enforcement actions. The suits bolstered other GPL projects, but companies switched away from using BusyBox. On the other hand, in-house counsel at some of the affected companies thanked those who brought the suits for making it easier to get the internal attention needed to address compliance issues.
Bird asked if anyone had evaluated removing McHardy's code from the kernel. Bottomley said that the Linux Foundation had done that analysis and found that there was simply too much of it to remove and replace. But Likely objected to the idea of removing the code at all, noting that the principles behind the GPL are important. Removing code that is covered by the GPL in order to avoid lawsuits is not the right way forward; it sends the wrong message to companies and others about what the GPL means.
Matthew Garrett said that the message about why compliance is a good thing needs to get out; the benefits of compliance need to be clear, since compliance for its own sake "doesn't gain us anything". The number of times where a company doesn't want to comply is small, but they are often unable to do so because they don't have the code or even know what was shipped. Compliance is not just about getting the code upstream, it is proof that the company even can be responsible to update their devices for security flaws.
Sandler said that manufacturers are starting to require complete source code from their vendors because of the need to be able to do security updates, rather than only to be able to comply with the GPL and other licenses. The television industry is definitely in that camp, Smith said. In a world where TVs listen to everything we say near them, access to the source code becomes even more important.
But it is not just about making sure the license is respected for existing code, Ted Ts'o said, it is also about making sure that new projects choose copyleft licenses. There have been some who are claiming that the GPL and other copyleft licenses are in decline. He also wondered about using the term "enforcement" as it is a word that can be scary. Sandler agreed and said that the SFC tries to use "compliance" in preference to "enforcement".
Transparency
Ts'o said that he knew that the SFC can't talk about all that it does, but that he would like to see some kind of report that at least gives an indication of how much compliance work is going on. He suggested something like the transparency reports that other organizations provide. It could show how many reports of violations were received and what compliance steps had been taken for those in general terms.
Sandler said that the SFC is working on figuring out how to get numbers out there. It is publishing what it can, but there are a number of privacy and other considerations that need to be taken into account. Ts'o suggested that reports of that nature could help with fundraising as some might be more inclined to "open their wallet if they could see progress" without resorting to lawsuits.
Pursuing GPL compliance is a tortuous process, Sandler said. Once the SFC is in contact with a violator, it often takes many rounds going back and forth with deliberate delays between each. On average, the SFC gets twenty different source candidates from a violator before getting a version that is complete and correct. In the VMware case, that process finally stalled out after three years or so before the SFC realized that litigation would be required.
Smith said that he was at the FSF when it sued Linksys. Before that happened, there was an "infinite loop" of finding a product with a license problem, starting to work to resolve that problem, then finding that a new product with the same license problems had been released. The Linksys compliance process simply wasn't working so, after four years of these discussions, it was time to escalate to a lawsuit.
There are a lot of small and medium-sized companies out there that are rattled and scared by the McHardy suits, Thomas Gleixner said. There is a need to get information to them so they know what to do and how to comply. Sandler agreed and asked if there were good ways to get that information to them. Gleixner suggested that various trade organizations and the like that had these companies as members might be one way to do so. It is important for those companies to get the information from the "good people" first, before they are contacted by McHardy.
One audience member wondered about compliance tests or certifications that vendors could use to demonstrate that they are following the licenses. That certification would allow buyers to choose suppliers who comply and would encourage vendors to comply instead of forcing them to through enforcement efforts. Smith noted that the FSF Respects Your Freedom certification goes further than just license compliance, but it does provide a carrot for suppliers.
Hellwig noted that most companies that work with software will already have some kind of compliance officer (or should). Most software licenses in the industry are complicated, but the GPL is quite simple.
With that, time was running out. Sandler said that the SFC only performs compliance activities as a service to and under the direction of the developers that are part of the coalition. The organization is trying to be as transparent as it can about those efforts and the BoF was part of that. She encouraged anyone with feedback to bring it to the SFC. Woodhouse ended things by encouraging developers to sign up with the compliance project so they could have a say in what direction those compliance efforts take.
[ Thanks to LWN subscribers for supporting my travel to Santa Fe for LPC. ]
The Ninja build tool
Ninja is a build tool, similar in spirit to make, that was born from the Chrome browser project in 2011. It is unique among build systems in that it was explicitly designed to be used as an "assembly language" by higher-level build tools. Beyond that, Ninja is fast. It is used by several large open-source projects and it has changed the way I approach build systems.
Ninja lacks many of the features that make users are familiar with: no conditionals, no string-manipulation functions, and no patterns or wildcards. Instead, you are supposed to put this logic into a separate program that generates Ninja build files; you aren't supposed to write Ninja build files by hand, though they are still quite readable. Some people write this generator program from scratch in a high-level language like Python, and they usually call it configure. Others use a build system such as CMake, GYP, or Meson, all of which can generate Ninja files based on rules written in their own custom language.
Despite its minimalist philosophy, Ninja does have a few features that make lacks: a progress report on its standard output, support for filenames with spaces, a "pools" mechanism to limit the parallelism of certain rules, and the ability to "include" other Ninja files without polluting the namespace of the including file. Ninja also has built-in support for some features that you could implement in a Makefile by using various techniques, but it's tedious to do so. I'll cover some of these in the article.
Rules and targets
A Ninja file to compile and link a C program from two source files might look like what's below. I have highlighted the targets (that is, the files that are created by the build process) in bold:
rule cc
command = gcc -c -o $out $in
description = CC $out
rule link
command = gcc -o $out $in
description = LINK $out
build source1.o: cc source1.c
build source2.o: cc source2.c
build myprogram: link source1.o source2.o
The last three lines are build statements. For example myprogram is a target, source1.o and source2.o are its inputs or dependencies, and link is the rule (defined a few lines earlier) that will build the target from the inputs. In the rule's command line, $out is replaced by the target and $in is replaced by the list of inputs, with the appropriate shell quoting. Ninja also supports implicit dependencies, implicit outputs, and order-only dependencies. Providing a description for a rule turns on automake-style silent rule output.
Auto-generated dependencies
In Makefiles, the standard technique for detecting changes to implicit dependencies (such as C header files) is to generate a small Makefile snippet that specifies the dependencies and to include this generated file into your main Makefile.
The equivalent technique in a Ninja file looks like this:
rule cc
command = gcc -c -o $out $in -MMD -MF $out.d
depfile = $out.d
deps = gcc
Here, -MMD tells GCC to output the list of included files and -MF says where to write it. Normal compilation happens too; the dependency file is generated as a side-effect of the compilation process. The depfile statement tells Ninja where to read those additional dependencies from. The first time you run Ninja, it will build the source1.o file because it is out of date compared to its explicit source1.c dependency. The next time Ninja is run, it will check to see if source1.c has changed or if any of the header files listed in depfile have changed. To support this technique, Ninja understands just the subset of Makefile syntax that is actually generated by C pre-processors. Ninja also supports a similar feature of the Microsoft Visual C++ compiler, which prints specially-formatted lines to stderr when given the /showIncludes flag.
Keeping track of build command lines
Ninja remembers the command line that was used to build each target. If the command line changes (probably because the build.ninja file itself changed), then Ninja will rebuild the target, even if the dependencies didn't change. Ninja tracks this information across invocations by storing a hash of the build command for each target in a .ninja_log file in the top-level build directory.
You can do this with Makefiles too — the technique is described here and it's used by the Makefiles for both Git and Linux. But it's tedious, error-prone, and slow.
Generating (and re-generating) the build file
Ninja doesn't support loops, wildcards, or patterns; you're supposed to generate the Ninja build file from another program. A simple configure script written in Python might look like this:
f = open("build.ninja", "w")
sources = ["source1.c", "source2.c"]
for source in sources:
f.write("build {outputs}: {rule} {inputs}\n".format(
outputs=source.replace(".c", ".o"),
rule="cc",
inputs=source))
# etc
If you want to support environment variables like $CFLAGS, it is best practice to read these variables in the configure script, and bake the values into the Ninja file. This makes it easier to maintain multiple build folders, such as a debug and a production build. The autotools behave this way.
Now if you edit your configure script to add another source file, source3.c, you'll want to ensure that build.ninja is re-generated. You can achieve this with another Ninja rule:
rule configure
command = ./configure
generator = 1
build build.ninja: configure
Thus, if build.ninja is out of date (older than configure), Ninja will run configure to re-create build.ninja, before it does anything else. The generator statement is necessary to exclude the target (the build.ninja file) from being removed by Ninja's auto-generated clean command. In practice, you would also want to remember any parameters originally given to configure (such as $CFLAGS), and bake them into the rule that re-runs configure.
If you're using a generator program like CMake, the principle is the same. The build.ninja file generated by CMake will arrange for itself to be re-generated if you edit CMake's build description file CMakeLists.txt.
Performance
Ninja's original motivation was speed. A no-op build of Chrome (where all the targets are already up to date) reportedly took 10 seconds with make, but less than a second with Ninja.
According to my own benchmarks, Ninja's speed difference is only really significant for very large projects (on Linux, at least). However I didn't try to implement, in make, my own version of Ninja's "rebuild if command-line changes", which would presumably slow the performance of make further.
Ninja generators and users
CMake is the most widely-used build system with Ninja support. CMake has always been a "meta build system" in that it generates build files for other build systems: various varieties of Makefiles, XCode project files for Mac, or Visual Studio project files for Windows. Since v2.8.8 in 2012, it can generate Ninja files as well.
GYP ("Generate Your Projects") is the build system used by Chromium and related projects such as the V8 JavaScript engine. As far as I know, it doesn't have much adoption elsewhere, and I don't know much about it.
Meson is a fairly recent build system that seems to be gaining traction. Unlike CMake, which seems to have come from the Windows world, Meson wants to provide first-class support for the Linux open-source ecosystem such as pkg-config, Gnome/GLib, etc., and the maintainers are happy to merge patches to support these types of projects. Maybe one day this will be able to replace autotools. (For many projects at least.) The GStreamer project recently merged "experimental" support for building with Meson — see this talk [video] at last month's GStreamer conference.
A few other Ninja generators are listed on the Ninja wiki, but it's hard to tell which of those are toy projects and which are suitable for large or complex projects.
Large projects that use Ninja include Chromium, of course; LLVM since 2012, via CMake; the Android Open Source Project, since late 2015, by parsing and translating GNU Makefiles; and GStreamer's experimental Meson-based build system mentioned above. Ninja is available in major Linux distributions — after all, it's needed to build Chromium. It's usually packaged as "ninja-build".
The Ninja community
Ninja was originally written by Evan Martin, who was working on the Chrome
browser, in 2011. Martin handed over maintainership in April 2014 to Nico Weber
(also on the Chrome team)
because
"I
actually haven't myself used Ninja in something like two years
",
he said,
having left the Chrome team. Even so, Martin is still active on the mailing list
and in the Git logs.
In the last two years, the release cadence has slowed down to one release every six to ten months. The feature set is pretty stable; these days the releases contain mostly bug fixes, though some useful new features do occasionally make their way in.
The latest major release (1.7.1 in April 2016) had 160 commits by 28 different contributors. 57% of the commits were from Weber and Martin, 14% from other Google employees, 5% from Kitware (the company behind CMake), 7% from a handful of other companies (SAP, Bloomberg, SciTools), and the remaining 17% of commits from 16 contributors whose company affiliation isn't obvious from the Git logs. The mailing list is fairly quiet, with a handful of threads per month, but it does include a good amount of feature discussion, not just support queries.
Some fairly obvious bugs are still open after four years: for example, Ninja doesn't support sub-second timestamp resolution. Other convenient features never get implemented (such as deleting output files if the build failed like GNU Make's .DELETE_ON_ERROR) partly because it's easy to implement workarounds in your Ninja-file generator. Keeping the Ninja codebase small and focused seems to be the driving philosophy. All in all the project seems healthy and mature. Ninja is written in C++ (12,000 lines of it, of which 40% are tests). It is released under the Apache 2.0 license.
Ninja's big idea
For me, Ninja's biggest contribution is to popularize the concept of generating build files from a real programming language. Many projects will find CMake or Meson to be a good fit, but when the needs are more complex, it can be surprisingly simple and elegant to use a real programming language like Python atop a dumb build system like Ninja or even a subset of make.
At $DAY_JOB, we build what is essentially a custom Linux distribution for appliances, with services packaged in Docker images. The build system was getting hard to debug and we were losing confidence in the correctness of incremental builds. We decided to try Ninja. Step one was to get rid of patterns and conditionals in the Makefiles, and write a Python script to generate the Makefiles. Step two was to output Ninja instead of make format. Before even getting to step two, however, we had already gained significant improvements in understandability, traceability, and debuggability.
Of course generating Makefiles is not a new idea — the autotools and CMake have been doing it for decades. But Ninja has taught me just how easy and flexible this approach is. For more information, Ninja's manual is a short and pleasant read. The free book "The Performance of Open Source Applications" has a chapter on Ninja that covers the original motivations for Ninja and some implementation details.
Kernel maintenance, Brillo style
The "Internet of things" has become a buzzword for a whole raft of new products, many of questionable value, that the industry would like to sell to us. It has also come to symbolize many of the problems afflicting the software development and delivery process. In a brief, fast-paced talk during the 2016 Linux Plumbers Conference's Android microconference, Kees Cook described how the Brillo project is trying to fix some of those problems, especially with regard to kernel maintenance.Brillo, he said, is a software stack for the Internet of things based on the Android system. These deployments bring a number of challenges, starting with the need to support a different sort of hardware than Android normally runs on; target devices may have no display or input devices, but might well have "fun buses" to drive interesting peripherals. The mix of vendors interested in this area is different; handset vendors are present, but many more traditional embedded vendors can also be found there. Brillo is still in an early state of development.
There are a number of longstanding problems endemic to this area. Each
device has its own special, static kernel version mixing changes from
multiple trees, including the mainline, the common Android tree, and any
vendor-specific trees. Fixes and new features must be backported to this
kernel, and out-of-tree drivers must be carried forward for future
products. As the number of products increases, the number of combinations
of kernels, patch sets, and hardware configurations grows exponentially,
leading to maintenance problems. This growth is relatively manageable
when the problems are small, but one of Brillo's requirements is device support
for at least five years after the last unit is sold. On that sort of time
scale, exponential growth in maintenance issues is simply not sustainable.
The solution to this problem, according to Cook, is a simple matter of making two changes:
- Maintain a single kernel for all systems, reducing patch combinations
and backporting work.
- Keep everything in the mainline kernel, reducing forward-porting work when a new kernel comes along.
Cook allowed as to how those principles might scare some vendors but, he said, if this approach seems too scary, "you're not testing enough."
Brillo is thus built in a single kernel tree containing the Android patches and all necessary vendor patches. This adds an interesting constraint, as it requires the vendors to all play well together with their own patches. These vendor patches should preferably be upstream anyway but, in any case, they must have been sent upstream for consideration. The kernel itself is the latest long-term support kernel from Greg Kroah-Hartman, and it follows the -stable updates as they are released. When a new long-term support kernel comes out, everything moves forward to that release.
Part of making this idea work is reducing the delta between the Brillo kernel and mainline. There are about 600 patches in the Android common kernel currently, Cook said; that has been reduced to less than 150 in the Brillo kernel. That was done by consolidating small patches, tweaking the Android user-space code to not need the patches in the first place, and upstreaming the patches that are easy to get merged.
The upgrade process has been tested once, in the move from the 4.1 to the 4.4 kernel. It went relatively easily and, happily, the list of add-on patches got quite a bit shorter, thanks to the upstreaming of a fair amount of vendor code. It was also possible to drop a whole bunch of backported patches, thanks to the newer kernel. This test may have only been run once so far but, Cook said, it demonstrates that the idea is "not entirely crazy."
For vendors who are afraid of regressions from kernel upgrades, Cook had some advice: get your code upstream. Then, create a better set of automatic tests to verify that everything is working. All vendors should be thinking about just what they fear might break and write tests to detect that when it happens. It is hard work, but it has to be done anyway to verify that things work in the first place; it also only has to be done once. Then perform regular testing on linux-next to catch problems before they end up in the next long-term support kernel.
Will this approach work? He certainly hopes so, he said. Something has to be done to get out of the "backport treadmill" that vendors are on now. Most vendors, he said, have already agreed to this approach, and they are becoming more proactive about upstreaming their code. Some vendors fear the five-year support rule but, for many in the embedded world, five years looks relatively short and doesn't bother them at all. "Handset vendors panic" at the idea, he said, but, in the end, they are going to have to decide between paying the up-front costs of upstreaming their code or the long-term costs of supporting old code for far longer than they have been accustomed to.
[Thanks to LWN subscribers for supporting our travel to the event.]
No LWN Weekly Edition next week
November 24 is the traditional Thanksgiving holiday in the US. As is our own tradition, we'll be taking the week off on the theory that we will have eaten too much food to get any useful work done anyway. The front-page stream will be occasionally updated as usual, and we'll be back to normal operations for the December 1 edition. Happy Thanksgiving to all who are celebrating it — and those who aren't as well.
Security
The bumpy road to reference-count protection in the kernel
When Kees Cook discussed kernel hardening at the 2016 Kernel Summit, the implementation of reference-count hardening was one of the prominent items on his list of objectives for the coming year. Since then, the topic has been discussed anew on the kernel mailing lists, and reference-count hardening has run into the sorts of problems that security-related patches often encounter: security changes are not always a comfortable fit with the objectives of a general-purpose, widely used kernel. It this case, it looks like the kernel will eventually get reference-count hardening, but not in the form that has been proposed thus far.When reference-count hardening was covered here last July, most of the attention was on a PaX-derived patch set posted by David Windsor. More recently, this patch set has been taken over by Elena Reshetova, who posted a new revision on November 10. The basic approach taken by the patch set has not changed: the kernel's atomic_t type, which is the usual choice for reference-count implementations, is instrumented to detect potential overflows. When an overflow happens, warnings are issued, the offending process is killed, and the affected counter is frozen at a high value so that it will never return to zero. That turns a potential use-after-free vulnerability into a memory leak, hopefully closing off an avenue of attack.
This time around, the patches ran into some stronger opposition, much of which came from core developer Peter Zijlstra. He had two fundamental objections to the approach taken with these patches; the first of those is that they do not preserve the atomic nature of atomic_t, leaving code open to certain kinds of race conditions. This race condition, which was known to Cook and others, could allow an attacker to bypass the reference-count protection. The conclusion that had been reached was that the risk was acceptable and that, in particular, the bypass could still be detected, even if it could not be prevented.
In a sense, the fact that this vulnerability has not been fixed in the hardening patches can be seen as a result of the pressure that developers of security-related patches are under. The vulnerability is easy to close by using a compare-and-swap instruction for reference-count changes, but that would have an adverse effect on performance. Security-related code is hard enough to merge even without performance regressions; in this case, the developers decided to stick with a less-than-perfect implementation to avoid slowing the kernel down. But Zijlstra was adamant that atomic operations must be atomic, even if there is a cost to be paid by users who want the reference-count protection.
The harder problem to solve, though, is tied to the fundamental approach
used by this patch set. It changes the atomic_t implementation on
the assumption that most users are implementing reference counts. It then
becomes necessary to go through the kernel, find all non-reference-count
uses of atomic_t, and switch them to an unprotected variable type.
This approach is necessary, Cook said, to
ensure that all reference-count vulnerabilities have been closed off:
"We need a hardened infrastructure, not just 'stuff people can maybe
remember to use'
". The only way to get there, he said, is with an
opt-out implementation.
The problem with this approach, in the eyes of the core kernel developers, is that it requires an audit of the entire kernel to find the non-reference-count users, and that is an error-prone process at best. Beyond that, atomic_t offers a wide range of operations that are not relevant to reference counts; making them available to developers implementing reference counts is just asking for trouble. In this view, it is far better to create a new type for reference counts, implement overflow protection there, and switch reference-count users over.
Back in June, Jann Horn suggested this approach, using the existing kref type for reference counts. That work didn't get much further at that time, but the approach has returned in the form of a new patch set from Zijlstra. Therein, he creates a new, protected refcount_t type; it is implemented using atomic_t and provides a restricted set of operations. The kref implementation is then reworked to use refcount_t, cleaning up some of the interfaces and users along the way. The intended end result is a well-defined way to implement reference counts in the kernel that is difficult for developers to abuse and which can be protected from overflow vulnerabilities.
The current reference-count hardening patch set from Reshetova touches nearly 400 files; Zijlstra's patch set is far smaller. To a great extent, that is because its ambitions are far lower: it adds an infrastructure for protecting reference counts and implements it for code that was already using the kref type, but does nothing about the vast number of reference-count implementations built directly on atomic_t; that is an exercise left for others to do later. The exercise is straightforward, but it does involve understanding the code in question to be sure that the switch to the new type will not introduce bugs.
Assuming that the kernel adopts Zijlstra's approach — a reasonably safe assumption — it will end up with a reference-count protection mechanism that runs more slowly and, initially, protects far less code than the PaX-derived approach. But it will also get a solution without race-condition worries and which doesn't have the same potential to introduce bugs into code using atomic_t for purposes other than reference counting. Over time, assuming developers devote some time to the task (not always a good assumption, alas), vulnerable code should be switched over and the end result, from a protection point of view, should be the same. For security-related patches, that sort of outcome is often the best-case scenario, even if the developers who put much of their time into the PaX-derived code find it less than fully gratifying.
Brief items
Security quotes of the week
Security experts frequently discover vulnerabilities in consumer electronics, but this case is exceptional. It was not a bug. Rather, Adups intentionally designed the software to help a Chinese phone manufacturer monitor user behavior, according to a document that Adups provided to explain the problem to [phone maker] BLU executives. That version of the software was not intended for American phones, the company said.
In general, the software market demands that products be fast and cheap and that security be a secondary consideration. That was okay when software didn't matter — it was okay that your spreadsheet crashed once in a while. But a software bug that literally crashes your car is another thing altogether. The security vulnerabilities in the Internet of Things are deep and pervasive, and they won't get fixed if the market is left to sort it out for itself. We need to proactively discuss good regulatory solutions; otherwise, a disaster will impose bad ones on us.
Security Exercises (Linux Journal)
Over at Linux Journal, Susan Sons has a lengthy article on security exercises, which are a way to test the readiness of a project or organization for some kind of security problem. "Scheduling exercises at a predictable time and reminding others when it will happen prevents confusion among staff. It is wise to begin with low-impact exercises (more on this below) that don't leverage production systems, and move on to higher-potential-impact exercises only when the organization's infrastructure and personnel have had most of the bugs shaken out. If something as small as a runaway process on a single server can seriously impact your business, it's better to find out at a planned time with all hands on deck than at 4am on a holiday when no one who knows what to do can be reached. The whole point of security exercises is to increase resilience: raise the threshold of what is normal for your team to deal with, what your systems can shrug off." She followed that article up with some example security exercises.
KDE neon users may want to reinstall
The KDE Project has a little problem to report for users of the KDE neon distribution: "The package archive used by KDE neon was incorrectly configured allowing anyone to upload packages to it. There is no reason to think that anyone actually did so but as a precaution we have emptied the archives and removed ISOs built before this date." Once the process of rebuilding the archive is complete, users are recommended to upgrade to the new versions, or, better, simply reinstall.
The "cryptsetup initrd root shell" vulnerability
Hector Marco and Ismael Ripoll report a discouraging vulnerability in many encrypted disk setups: simply running up too many password failures will eventually result in a root shell. "This vulnerability allows to obtain a root initramfs shell on affected systems. The vulnerability is very reliable because it doesn't depend on specific systems or configurations. Attackers can copy, modify or destroy the hard disc as well as set up the network to exfiltrate data. This vulnerability is specially serious in environments like libraries, ATMs, airport machines, labs, etc, where the whole boot process is protect (password in BIOS and GRUB) and we only have a keyboard or/and a mouse."
New vulnerabilities
akonadi: denial of service
| Package(s): | akonadi | CVE #(s): | |||||||||
| Created: | November 16, 2016 | Updated: | November 18, 2016 | ||||||||
| Description: | From the Debian advisory:
In some configurations the MySQL storage backend for Akonadi, an extensible cross-desktop Personal Information Management (PIM) storage service failed to start after applying the MySQL 5.5.53 security upgrade. | ||||||||||
| Alerts: |
| ||||||||||
atomic-openshift: redirect network traffic
| Package(s): | atomic-openshift | CVE #(s): | CVE-2016-8631 | ||||
| Created: | November 16, 2016 | Updated: | November 16, 2016 | ||||
| Description: | From the Red Hat advisory:
The OpenShift Container Platform 3 router does not properly sort routes when processing newly added routes. An attacker with access to create routes can potentially overwrite existing routes and redirect network traffic for other users to their own site. | ||||||
| Alerts: |
| ||||||
chromium-browser: multiple vulnerabilities
| Package(s): | chromium-browser | CVE #(s): | CVE-2016-5199 CVE-2016-5200 CVE-2016-5201 CVE-2016-5202 | ||||||||||||||||||||||||||||||||||||||||||||
| Created: | November 15, 2016 | Updated: | November 29, 2016 | ||||||||||||||||||||||||||||||||||||||||||||
| Description: | From the Red Hat advisory:
Multiple flaws were found in the processing of malformed web content. A web page containing malicious content could cause Chromium to crash, execute arbitrary code, or disclose sensitive information when visited by the victim. | ||||||||||||||||||||||||||||||||||||||||||||||
| Alerts: |
| ||||||||||||||||||||||||||||||||||||||||||||||
dracut: information disclosure
| Package(s): | dracut | CVE #(s): | CVE-2016-8637 | ||||||||||||
| Created: | November 10, 2016 | Updated: | November 21, 2016 | ||||||||||||
| Description: | From the Red Hat bugzilla entry:
A local information disclosure issue was found in dracut when generating initramfs images with world-readable permissions when "early cpio" is used, such as when including microcode updates. Local attacker can use this to obtain sensitive information from these files, such as encryption keys or credentials. | ||||||||||||||
| Alerts: |
| ||||||||||||||
firefox: multiple vulnerabilities
| Package(s): | firefox thunderbird | CVE #(s): | CVE-2016-5290 CVE-2016-5291 CVE-2016-5296 CVE-2016-5297 CVE-2016-9064 CVE-2016-9066 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Created: | November 16, 2016 | Updated: | December 15, 2016 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Description: | From the Red Hat advisory:
* Multiple flaws were found in the processing of malformed web content. A web page containing malicious content could cause Firefox to crash or, potentially, execute arbitrary code with the privileges of the user running Firefox. (CVE-2016-5296, CVE-2016-5297, CVE-2016-9066, CVE-2016-5291, CVE-2016-5290) * A flaw was found in the way Add-on update process was handled by Firefox. A Man-in-the-Middle attacker could use this flaw to install a malicious signed add-on update. (CVE-2016-9064) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Alerts: |
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
gst-plugins-bad0.10: code execution
| Package(s): | gst-plugins-bad | CVE #(s): | CVE-2016-9447 | ||||||||||||||||||||||||||||||||||||||||||||||||
| Created: | November 16, 2016 | Updated: | December 16, 2016 | ||||||||||||||||||||||||||||||||||||||||||||||||
| Description: | From the Debian advisory:
Chris Evans discovered that the GStreamer 0.10 plugin to decode NES
Sound Format files allowed the execution of arbitrary code. Further
details can be found in his advisory at | ||||||||||||||||||||||||||||||||||||||||||||||||||
| Alerts: |
| ||||||||||||||||||||||||||||||||||||||||||||||||||
kernel: two vulnerabilities
| Package(s): | kernel | CVE #(s): | CVE-2016-7097 CVE-2016-8666 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Created: | November 10, 2016 | Updated: | January 31, 2017 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Description: | From the Mageia advisory:
The filesystem implementation in the Linux kernel through 4.8.2 preserves the setgid bit during a setxattr call, which allows local users to gain group privileges by leveraging the existence of a setgid program with restrictions on execute permissions (CVE-2016-7097). The IP stack in the Linux kernel before 4.6 allows remote attackers to cause a denial of service (stack consumption and panic) or possibly have unspecified other impact by triggering use of the GRO path for packets with tunnel stacking, as demonstrated by interleaved IPv4 headers and GRE headers, a related issue to CVE-2016-7039 (CVE-2016-8666). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Alerts: |
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
libarchive: unspecified
| Package(s): | libarchive | CVE #(s): | |||||
| Created: | November 16, 2016 | Updated: | November 16, 2016 | ||||
| Description: | From the Mageia advisory:
The updated packages might contain additional security fixes if we missed some other ones when we cherry-picked patches against version 3.2.1. | ||||||
| Alerts: |
| ||||||
libgit2: unspecified
| Package(s): | libgit2 | CVE #(s): | |||||||||
| Created: | November 15, 2016 | Updated: | November 21, 2016 | ||||||||
| Description: | libgit2-v0.24.3 fixes unspecified vulnerabilities. See the Red Hat advisory for more information. | ||||||||||
| Alerts: |
| ||||||||||
monit: cross-site request forgery
| Package(s): | monit | CVE #(s): | CVE-2016-7067 | ||||||||||||||||||||
| Created: | November 14, 2016 | Updated: | December 13, 2016 | ||||||||||||||||||||
| Description: | From the Mageia advisory:
The forms in Monit's Service Manager are vulnerable to a cross site request forgery attack. Successful exploitation will enable an attacker to disable/enable all monitoring for a particular host, disable/enable monitoring for a specific service. | ||||||||||||||||||||||
| Alerts: |
| ||||||||||||||||||||||
mysql-community-server: multiple unspecified vulnerabilities
| Package(s): | mysql-community-server | CVE #(s): | CVE-2016-5507 CVE-2016-5609 CVE-2016-5627 CVE-2016-8284 CVE-2016-8288 | ||||||||||||||||||||
| Created: | November 14, 2016 | Updated: | November 16, 2016 | ||||||||||||||||||||
| Description: | From the CVE entries:
Unspecified vulnerability in Oracle MySQL 5.6.32 and earlier and 5.7.14 and earlier allows remote administrators to affect availability via vectors related to Server: InnoDB. (CVE-2016-5507) Unspecified vulnerability in Oracle MySQL 5.6.31 and earlier and 5.7.13 and earlier allows remote authenticated users to affect availability via vectors related to DML. (CVE-2016-5609) Unspecified vulnerability in Oracle MySQL 5.6.31 and earlier and 5.7.13 and earlier allows remote authenticated users to affect availability via vectors related to Server: InnoDB. (CVE-2016-5627) Unspecified vulnerability in Oracle MySQL 5.6.31 and earlier and 5.7.13 and earlier allows local users to affect availability via vectors related to Server: Replication. (CVE-2016-8284) Unspecified vulnerability in Oracle MySQL 5.6.30 and earlier and 5.7.12 and earlier allows remote authenticated users to affect integrity via vectors related to Server: InnoDB Plugin. (CVE-2016-8288) | ||||||||||||||||||||||
| Alerts: |
| ||||||||||||||||||||||
nss, nss-util: two vulnerabilities
| Package(s): | nss nss-util | CVE #(s): | CVE-2016-5285 CVE-2016-8635 | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| Created: | November 16, 2016 | Updated: | November 16, 2016 | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| Description: | From the Red Hat advisory:
* A NULL pointer dereference flaw was found in the way NSS handled invalid Diffie-Hellman keys. A remote client could use this flaw to crash a TLS/SSL server using NSS. (CVE-2016-5285) * It was found that Diffie Hellman Client key exchange handling in NSS was vulnerable to small subgroup confinement attack. An attacker could use this flaw to recover private keys by confining the client DH key to small subgroup of the desired group. (CVE-2016-8635) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Alerts: |
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||
opera: multiple vulnerabilities
| Package(s): | opera | CVE #(s): | |||||||||
| Created: | November 14, 2016 | Updated: | November 16, 2016 | ||||||||
| Description: | From the openSUSE advisory:
This update to Opera 41.0.2353.56 fixes the following issues:
| ||||||||||
| Alerts: |
| ||||||||||
python-cryptography: bad key generation
| Package(s): | python-cryptography | CVE #(s): | CVE-2016-9243 | ||||||||||||||||||||
| Created: | November 14, 2016 | Updated: | November 29, 2016 | ||||||||||||||||||||
| Description: | From the Mageia advisory:
Fixed a bug where HKDF would return an empty byte-string if used with a length less than algorithm.digest_size. | ||||||||||||||||||||||
| Alerts: |
| ||||||||||||||||||||||
qemu: multiple vulnerabilities
| Package(s): | qemu, qemu-kvm | CVE #(s): | CVE-2016-7421 CVE-2016-7423 CVE-2016-7994 CVE-2016-8668 | ||||||||||||||||||||||||||||||||
| Created: | November 10, 2016 | Updated: | November 16, 2016 | ||||||||||||||||||||||||||||||||
| Description: | From the Ubuntu advisory:
Li Qiang discovered that QEMU incorrectly handled VMWARE PVSCSI paravirtual SCSI bus emulation support. A privileged attacker inside the guest could use this issue to cause QEMU to crash, resulting in a denial of service. (CVE-2016-7156, CVE-2016-7421) Li Qiang discovered that QEMU incorrectly handled LSI SAS1068 host bus emulation support. A privileged attacker inside the guest could use this issue to cause QEMU to crash, resulting in a denial of service. (CVE-2016-7423) Li Qiang discovered that QEMU incorrectly handled the Virtio GPU support. A privileged attacker inside the guest could use this issue to cause QEMU to consume resources, resulting in a denial of service. (CVE-2016-7994) It was discovered that QEMU incorrectly handled Rocker switch emulation support. A privileged attacker inside the guest could use this issue to cause QEMU to crash, resulting in a denial of service. (CVE-2016-8668) | ||||||||||||||||||||||||||||||||||
| Alerts: |
| ||||||||||||||||||||||||||||||||||
rh-mysql56-mysql: privilege escalation
| Package(s): | rh-mysql56-mysql | CVE #(s): | CVE-2016-6664 | ||||||||||||||||||||||||||||||||||||
| Created: | November 15, 2016 | Updated: | January 19, 2017 | ||||||||||||||||||||||||||||||||||||
| Description: | From the Red Hat advisory:
A flaw was found in the way the mysqld_safe script handled creation of error log file. The mysql operating system user could use this flaw to escalate their privileges to root. | ||||||||||||||||||||||||||||||||||||||
| Alerts: |
| ||||||||||||||||||||||||||||||||||||||
sudo: privilege escalation
| Package(s): | sudo | CVE #(s): | CVE-2016-7032 | ||||||||||||||||||||||||||||||||||||
| Created: | November 15, 2016 | Updated: | November 16, 2016 | ||||||||||||||||||||||||||||||||||||
| Description: | From the Debian LTS advisory:
It was discovered that the sudo noexec restriction could have been bypassed if application run via sudo executed system(), popen() or wordexp() C library functions with a user supplied argument. A local user permitted to run such application via sudo with noexec restriction could possibly use this flaw to execute arbitrary commands with elevated privileges. noexec bypass via system() and popen() | ||||||||||||||||||||||||||||||||||||||
| Alerts: |
| ||||||||||||||||||||||||||||||||||||||
sudo: privilege escalation
| Package(s): | sudo | CVE #(s): | CVE-2016-7076 | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| Created: | November 14, 2016 | Updated: | November 25, 2016 | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| Description: | From the Red Hat advisory:
It was discovered that the sudo noexec restriction could have been bypassed if application run via sudo executed wordexp() C library function with a user supplied argument. A local user permitted to run such application via sudo with noexec restriction could possibly use this flaw to execute arbitrary commands with elevated privileges. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Alerts: |
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||
terminology: command execution
| Package(s): | terminology | CVE #(s): | CVE-2015-8971 | ||||
| Created: | November 14, 2016 | Updated: | November 16, 2016 | ||||
| Description: | From the Debian advisory:
Nicolas Braud-Santoni discovered that incorrect sanitising of character escape sequences in the Terminology terminal emulator may result in the execution of arbitrary commands. | ||||||
| Alerts: |
| ||||||
tre: code execution
| Package(s): | tre | CVE #(s): | CVE-2015-3796 | ||||||||||||||||
| Created: | November 15, 2016 | Updated: | November 16, 2016 | ||||||||||||||||
| Description: | From the CVE entry:
The TRE library in Libc in Apple iOS before 8.4.1 and OS X before 10.10.5 allows context-dependent attackers to execute arbitrary code or cause a denial of service (memory corruption and application crash) via a crafted regular expression, a different vulnerability than CVE-2015-3797 and CVE-2015-3798. | ||||||||||||||||||
| Alerts: |
| ||||||||||||||||||
Page editor: Jake Edge
Kernel development
Brief items
Kernel release status
The current development kernel is 4.9-rc5, released on November 13. Linus said: "Things have definitely gotten smaller, so a normal release schedule (with rc7 being the last one) is still looking possible despite the large size of 4.9. But let's see how things work out over the next couple of weeks. In the meantime, there's a lot of normal fixes in here, and we just need more testing."
Stable updates: 4.8.7 and 4.4.31 were released on November 10, followed by 4.8.8 and 4.4.32 on November 15.
Quotes of the week
I'd restrict this to reasonably 'deterministic' holes, and the exploits themselves could be somewhere in tools/. (Obviously only where the maintainers agree to host the code.)
Kernel development news
Scheduling for Android devices
The Android/Mobile microconference at the 2016 Linux Plumbers Conference was a grueling seven-hour affair. Your editor was unable to attend the entire session, but was fortunate enough to be present for a series of talks on scheduling. Adding better awareness of power usage to the scheduler has been a recurring topic for some years; that didn't change this year, but there was also a focus on improving the user experience in general.Todd Kjos started by talking about scheduling for the Nexus 5X handset, which was the first of Google's devices to be based on the big.LITTLE processor architecture. This handset has four A53 and two A57 cores in it; the A53s are relatively slow and power-efficient, while the A57s offer higher performance. Tuning Android to run well on this device has turned out to be challenging. The objectives are straightforward enough: workloads that the user doesn't care about should run on the A53 cores, but performance-sensitive loads should not get stuck on those cores. When not much is being done, the A57 cores should not be running at all. But achieving those objectives has taken some work.
It would be nice to avoid repeating that work for each new device, but
generic support for energy-aware scheduling still has not found its way
into the mainline kernel. Instead, each system-on-chip (SoC) vendor
provides its own heavily patched kernel with its own solution to the
scheduling problem. Some of these vendors, Kjos said, have done a
relatively good job with their scheduling patches; others less so. But,
either way, these out-of-tree patches mean that vendors have a lot of work
to do when new Android releases come along.
All of these solutions are hampered by a lack of knowledge about what is going on — and what the user most cares about — in user space. But the Android framework does have an idea about what is going on there. At any given time, Android knows what the "top app", the app that the user actually sees and interacts with, is. It is aware of other "foreground" apps that are a part of the user experience; they may be drawing other parts of the screen or occupying a part of a split screen. Then, there are the "background" processes that are not currently a part of the user's experience and are, thus, less important.
Beyond that, the Android framework is aware of user interaction events, such as touches and swipes, and some other aspects of the workload, including things like video frame rates. That is a lot of information about what is going on, but that information is not being exploited on most devices currently.
The scheduler on an Android device should provide the best experience for the user while being as energy-efficient as possible. The latter goal implies getting proper energy-aware scheduling support into the mainline kernel. A common solution would allow Android to perform workload-specific tuning in a generic manner and would reduce the amount of SoC-specific code carried by manufacturers and vendors. As CPU topologies become more complex, the need to provide a better, saner strategy grows.
Energy-aware scheduling, as presented by Kjos, consists of three major components. The first of those is the core scheduler changes allowing it to use CPU topology to place running processes optimally. Some of that work has found its way into the mainline, and progress is being made on the rest. Next is improved frequency and voltage selection for the running processors to maximize efficiency; the plan here is to switch over to the mainline schedutil framework, which can make better use of what the scheduler knows to configure the CPU operating parameters. The last piece is the out-of-tree SchedTune subsystem, which allows Android to tweak scheduling policies on the fly.
A digression into SchedTune
Your editor will now indulge in a bit of temporal manipulation. Patrick Bellasi presented the SchedTune governor later that day, but the information provided then is useful for the understanding of the rest of Kjos's talk. In the interest of a better narrative, we'll take a quick look at SchedTune now.
The kernel's current CPU-frequency governors attempt to match the CPU's operating power points (its frequency and voltage) to the workload that is actually being run. A light workload can be run at a relatively low frequency and voltage, saving power, but heavier workloads require the CPU to be running in a more energy-intensive mode. The optimal power point, he said, should be chosen with the user's needs in mind; sometimes response time is crucial to the user's experience, while, at other times, workloads can be run more slowly and nobody will notice.
Unfortunately, the scheduler knows little about which processes are
important to the user at any given time. On Android systems, the runtime
system does have a good idea of what matters, but there is no good way to
communicate that information to the scheduler. The SchedTune governor is meant to be a way to
provide that information so that the scheduler can act on it.
In current kernels, the load-tracking subsystem maintains an estimate of just how much load each running process will put onto the system. Recent changes have enabled CPU-frequency governors to make use of that information to set the power points optimally; usually, the objective is to run the CPUs just fast enough to get the anticipated amount of work done. Governor policy can be changed into, for example, a "performance" mode where the objective is to get the work done as quickly as possible, but there is no way to set CPU-frequency policies on a per-task basis or, in other words, to tell the system that it is worthwhile to expend a certain amount of extra energy to get a specific job done.
SchedTune is implemented as a control-group controller. Each control group has a single tunable knob, called schedtune.boost, which can be used by the runtime system to change how processes within that group are scheduled. This parameter works in an interesting manner: it tweaks the load-tracking code to make the affected processes look heavier (or lighter) than they really are. If a group is boosted by 25%, the scheduler will expect it to use 25% more CPU time than it (probably) actually will, and the CPU-frequency governor will speed up the processor accordingly. "Boosting" a process in this way, thus, does not affect its scheduling priority, but it will affect the speed of the CPU on which it ends up running.
Bellasi concluded with some proposals for future enhancements to SchedTune. One of those would be to tweak scheduling further so that processes with a positive boost value would get longer time slices in the CPU. A couple more knobs may be added to the control group to affect the CPUs on which processes may be run; they would specify the minimum and maximum performance capacity that a candidate CPU may have. To summarize, while SchedTune is already in use in shipping products, it is still in a certain amount of flux.
Energy-aware scheduling in the Pixel phone
Returning to Kjos's talk: with these components in mind, he and others set out to implement proper energy-aware scheduling in the Pixel phone; the initiative began after a meeting at the 2015 Linux Plumbers Conference. Some experiments with energy-aware scheduling on a tablet device yielded good results, so a group of engineers from ARM, Qualcomm, and Google decided to collaborate on a solution for the Pixel. The group had a significant challenge: come up with a relatively generic energy-aware scheduling solution that worked at least as well as Qualcomm's out-of-tree QHMP scheduling patches.
Getting there required a number of modifications to the existing energy-aware scheduling code. Its view of big.LITTLE processors doesn't quite fit the Snapdragon 821 used in the Pixel, so some of those assumptions had to be changed. SchedTune and cpusets were adopted to allow the Android framework to specify how processes should be placed in the system and, in particular, whether specific processes should be spread out to idle CPUs or packed into a small number of CPUs. SchedTune was also enhanced to allow tasks to be marked as latency-sensitive.
The kernel's per-entity load tracking mechanism, by which the scheduler tracks how much load each process puts on the system, proved to not be up to the task of getting the best performance out of this processor, so the out-of-tree window-assisted load tracking (WALT) mechanism was used instead. Nobody discussed the WALT patches in detail during the microconference, but they do play a significant part in this work, and thus merit a quick discussion.
Digression 2: WALT
Per-entity load tracking was added to the 3.8 kernel to fill in a gap in the scheduler's understanding: it didn't have any way to know how much load any given process would put on the CPU. That information is useful for load balancing — distributing processes optimally across the CPUs in the system — and for knowing what will happen if a process is moved from one CPU to the next. Each process's load is calculated using a simple geometric series, with the most recent load being counted most heavily.
This mechanism is an improvement over what came before, but it turns out to not work ideally, especially in the mobile world. The biggest complaint seems to be that it is simply too slow to respond to changes in a process's behavior. A web browser that has been idle for a long time, with a correspondingly low calculated load, may suddenly find itself rendering a complex page and needing a lot of CPU. If its associated load does not rise quickly enough, that browser process will not get enough CPU time (because it must share a CPU with too many others, putting the system out of balance, or because the CPU frequency will not be increased as needed) while it is trying to do its work. The result is slow response as seen by the increasingly grumpy user.
The problem also exists when processes stop using the CPU. Per-entity load tracking will take some time to notice that the load is gone, with the result that the CPU will stay in a higher power state than it actually needs to be, shortening battery life. To make things worse, processes that are not runnable (waiting on I/O, for example) are counted as part of the load, even though they are not doing anything and may not for some time.
The WALT patches do away with the geometric series for load calculations. Instead, WALT simply tracks the amount of CPU time used by the process during a set of recent "windows" of time. According to the patch description, "N" windows are maintained, and a process's calculated load is the maximum of either the most recently completed window or the average of all N windows. The actual patch, as posted, appears to keep around exactly one 20ms window, so the most recent measurement and the average are one and the same. In essence, WALT has modified per-entity load tracking by chopping off all but the first term in the geometric load-calculation series. There is one other significant change: tracking is only done while the process is running; a process will not contribute to system load while it is waiting for something, and its previous load calculation will still be there once it becomes runnable again.
This algorithm causes WALT to respond much more quickly to a process's behavior; if a process begins some sort of CPU-intensive activity, its calculated load will quickly rise to match. It is thus useful for tasks like setting the CPU frequency. It may not work as well as per-entity load tracking for the long-term balancing of processes across the system; for this reason, the latter numbers are still used for load-balancing decisions.
The WALT patches got a bit of a grumpy reception from scheduler maintainer Peter Zijlstra, who would have liked to have seen them before they started shipping in production devices. He agrees that the current load-tracking numbers fall short of what is really needed, but would like to see something like WALT added to the existing load-tracking code, rather than being bolted on alongside it. So the WALT patches are likely to change significantly before they can be considered for merging.
Finishing out the Pixel story
Returning once again to Kjos's talk: WALT, along with SchedTune, was needed to achieve the sort of response time and power savings needed for the Pixel phone. The sched-freq CPU governor (still in use in the Pixel) needed some tweaking as well; in particular, it was changed to ramp up CPU frequencies quickly, but to lower them more slowly. That ensures that processes needing CPU time will get it right away, and the CPU won't be yanked out from underneath them too quickly afterward.
Once the necessary software components were in place, it was time to set policies in SchedTune and the cpuset controller. The top app at any given time is set to a "spread" policy, meaning it is likely to find itself running on its own CPU. It is also given a 10% boost to ensure that it gets enough CPU time. Foreground tasks also get the "spread" policy, but without the boost, while background tasks are given a "pack" policy, causing them to be concentrated on relatively few CPUs — often just one. Kernel threads and other system processes also run with the pack policy. To further constrain placement, cpusets are used to keep background tasks on the two slower CPUs; the top app and foreground tasks share one fast CPU, while the top app gets the other fast CPU to itself.
The results (seen toward the end of Kjos's slides) show that the new scheduling code achieved or exceeded the performance of QHMP on almost all metrics. The code has been merged into the Android 3.18 and 4.4 kernel trees, and has been enabled on the Pixel device; it can also be found on the Acer R13 Chromebook and on development boards like the 96Boards HiKey. The move to the schedutil governor should happen within the next year. And, of course, the group is working to get these changes merged upstream.
Epilogue: realtime scheduling
Mechanisms like SchedTune give the Android developers better control over how the scheduler responds to user-space changes. But there is another way to get low-latency response from a Linux kernel: use its realtime capabilities. Juri Lelli gave a brief talk on how Android is using realtime scheduling now, and how things may change in the near future.
The SCHED_FIFO realtime scheduling class, which allows a realtime
process to run uninterrupted until either it sleeps or a
higher-priority realtime process comes along, is used for some
latency-sensitive processes in Android now. In particular, the
SurfaceFlinger display manager uses it, as do the audio pipeline and the
threads for CPU-frequency management. There are other latency-sensitive
processes that are not using realtime scheduling at this time; these
include the user-interface and rendering threads.
Why are those threads not using realtime scheduling? The scheduler's load balancing is "naive" when it comes to realtime processes, he said, so they do not get properly distributed across the CPUs. By design, the realtime scheduler will throttle processes once they use about 95% of the available CPU time; that mechanism is there to prevent a runaway realtime process from killing the system completely, but it can also get in the way when that CPU time is needed. Even with that protection, though, there is also a fear that a bug in one of those processes could cause them to take over the CPU and kill the system.
These issues notwithstanding, the near-future hope is to move to SCHED_FIFO for the user-interface and rendering threads. Getting there will require a few changes, starting with tweaks to the user-space code that will hopefully be released in the Android Open Source Project in December. The realtime CPU-selection (load balancing) code will be given better energy awareness; those patches have yielded significant efficiency improvements in benchmark testing so far. There is also work on a new TEMP_FIFO scheduling class that would get around the throttling problem by allowing realtime tasks to continue executing, at normal priority under the completely fair scheduler, if they exceed the maximum CPU time allowed in realtime mode.
There is an alternative to changing the behavior of SCHED_FIFO, though: use the deadline scheduler instead. This scheduler can allow latency-sensitive tasks to get their work done with less risk of them taking over the system. There are, however, a number of shortcomings with the deadline scheduler that need to be dealt with first. These include proper control-group support and integration with the schedutil CPU-frequency governor. The deadline scheduler, too, needs a means by which a process can continue executing, at normal priority, when it exceeds the CPU time allotted to it.
Should it be possible to fix these issues, the plan is to use the SurfaceFlinger thread as the first guinea pig for deadline scheduling. Then, perhaps, deadline scheduling will finally see a widespread, real-world deployment.
[Thanks to LWN subscribers for supporting our travel to the event.]
Topics in live kernel patching
Getting live-patching capabilities into the mainline kernel has been a multi-year process. Basic patching support was merged for the 4.0 release, but further work has been stalled over disagreements on how the consistency model — the code ensuring that a patch is safe to apply to a running kernel — should work. The addition of kernel stack validation has addressed the biggest of the objections, so, arguably, it is time to move forward. At the 2016 Linux Plumbers Conference, developers working on live patching got together to discuss current challenges and future directions.This article is not an attempt at a comprehensive summary for a half-day of fast-moving discussion; instead, the goal is to cover some of the more interesting topics as a way of showing that challenges that the live-patching developers must overcome and how they plan to get there.
Unhelpful optimizations
A smart optimizing compiler is necessary for anybody who wants to get reasonable performance from their code, but problems arise if the compiler gets too smart. Developers working with concurrency in the kernel have had to worry about aggressive optimizations for some time; according to Miroslav Benes, live-patching developers have to worry as well. Compiler optimizations can change how code is compiled in subtle ways that can lead to mayhem when a patch is applied.
Starting with the easiest problems before moving on to the trickier ones,
Benes noted that the automatic inlining of functions can be a problem if an
inlined function must be patched. In that case, the solution is relatively
easy; all callers of the function must be changed in the resulting live
patch. The -fpartial-inlining option can complicate things by
only inlining portions of functions, but it doesn't change the basic nature
of the problem.
The -fipa-src option is a bit more subtle, in that it can lead to the removal of unused function parameters or change the way in which parameters are passed into a function. In other words, it changes the ABI of the function in response to its observations on how the function works. A live patch to that function could change how this optimization operates, leading to a surprising change in the ABI. The good news here is that, when this happens, GCC will change the name of the compiled function, so the broken ABI is immediately obvious. But this can prevent the direct patching of a buggy function; callers must be patched as well.
Code compiled with -fipa-pure-const may change in response to how a function operates; if a function is seen as not accessing memory, the compiler will make assumptions about the state of memory before and after calling it. If a patch changes the function's behavior, those assumptions may no longer hold; once again, it will be necessary to patch callers when this happens.
An "even crazier" option is -fipa-icf, which performs identical code folding. It can cause a function to be entirely replaced by an equivalent found elsewhere in the code, and it can be hard to detect that this change has happened. Code folding is also a problem for the kernel's stack unwinder. Other types of code elimination can happen if GCC thinks that a specific global variable won't change over a given function call. If the function is patched to now change the global variable, the calling code may well be incorrect. This sort of change, too, is hard to detect; it would be nice, he said, to have a GCC option to ask it to create a log of the optimizations it has done.
Perhaps the scariest option is -fipa-ra, which tracks the registers used by called functions and avoids saving those that will not be changed. A patch to the called function could easily cause it to use a new register, leading to data corruption in the calling functions and a likely significant reduction in the continuous uptime that live-patching users were hoping to enjoy. This optimization is hard to detect; it can be thought of as an ABI change for the called function, but no name changes are made. This one, he said, is "not good news." For now, this optimization is disabled by GCC when -pg is turned on, and the Ftrace subsystem, needed for live patching, needs -pg. But there is no inherent reason why those two options need to be incompatible, so this behavior could change at any time.
This list, Miroslav said, is only a small subset of the optimizations that can create problems for live patches. As compiler developers pursue increasingly aggressive optimizations, this problem is only going to get worse.
Patch building
The kernel has a standard way to apply a live patch, but there is not, yet, any sort of mainlined mechanism for the creation of live patches. Josh Poimboeuf gave a brief summary of the patch-creation tools out there with an eye toward picking one for upstream.
The first of these is kpatch-build.
It works by building the kernel both with and without the patch applied,
then does a binary diff to see which functions changed. All of the changed
functions are then extracted and packaged up into a "Frankenstein kernel
module" that is shipped with the live patch. It is a powerful system, he
said, with a number of advantages, including the fact that it automatically
deals with most of the optimization issues mentioned in the previous talk.
On the other hand, kpatch-build is quite complex. It has to know about all of the special sections used by the kernel, and it has problems with certain kinds of changes. It only works on the x86_64 architecture at the moment; all of those special sections differ across architectures, so turning it into a multi-architecture tool will not be easy. And, he said, kpatch-build is brittle and a maintenance nightmare.
An alternative is to just use the regular kernel build system and its module-building infrastructure. The changed function is copied and pasted into a new module, some boilerplate is added to register the function with the live-patching API, and the job is done. It's easy, but has its own problems; in particular, this module is unable to access non-exported symbols, which the patched function may need to do. This problem can be worked around by using kallsyms_lookup_name(), but this solution is error-prone, slow, and "yucky."
The third alternative is new; indeed, he posted the proposal the week before the conference. This alternative uses the copy-and-paste approach, but adds an API and a postprocessing tool that allows the generated module to gain access to non-exported symbols. The code works now, though there are a number of possible improvements, including automating the process of attaching to non-exported symbols and detecting interference from compiler optimizations.
In the brief discussion at the end of the talk, it became clear that there were not a lot of concerns about the new tooling, so that is the direction things seem likely to go.
Module dependencies
Live patches can make changes to loadable modules, which leads to an interesting question: what happens if the module isn't present in the system when a patch is applied, but is loaded afterward? The live-patching code currently has some complicated infrastructure designed to detect this case and apply patches to modules as they are loaded. Jessica Yu, who has just taken over as the maintainer of the loadable module subsystem in the kernel, talked briefly about changing this mechanism to require that alle affected modules be loaded before a live patch is applied.
Live patches are, themselves, loadable modules. Allowing a patch module to
be loaded before any modules it affects requires carrying a fair amount of
information and complex infrastructure, and it circumvents the normal
module dependency mechanism. As a result, there is a fair amount of code
duplication, including a reimplementation of much of the module loader in
the live-patching code.
There are a couple of ways that things could be changed. One would be to simply require that all modules being patched be loaded before the patch itself is loaded. That would work, but it forces the loading of code into the kernel that is unneeded and may never be used on any given site. The alternative would be to split the live-patch module into multiple pieces, each of which applies a patch to a single kernel module. Then, only the pieces that are relevant to any given running system need to be loaded.
Making this change would simplify the live-patching code and reduce code duplication, but there's a problem: there isn't an easy way to force a necessary patch module to be loaded when a module needing patching is loaded. The depmod tool just doesn't recognize that sort of dependency. FreeBSD has a nice MODULE_DEPEND() macro, but Linux has never needed that infrastructure.
Splitting the patch module, it turns out, could be problematic for any sort of wide-ranging change. CVE-2016-7097 was mentioned as an example; it included a virtual filesystem layer API change that had to be propagated to all filesystems. If it were to be split apart, the result would be a long list of modules that would need to be loaded to apply the patch.
There was a lively discussion on whether the rules concerning live patches for modules should be changed, much of it focused on a question asked by Steve Rostedt: if a module isn't present in the kernel, why not just fix it on disk rather than lurking in the kernel, waiting to patch it should it ever be loaded? Jiri Kosina replied that replacing on-disk modules would be hard from a distributor's point of view; it would introduce modules that no longer belong to the kernel package. Live patches can also be disabled; in that case, modified modules would have to be somehow restored. Some consistency models can also create trouble; it is possible to have both the pre-patch and post-patch code live and running in the kernel at the same time. So it's not obvious that fixing things on-disk is a workable solution, though Rostedt was adamant that it should be considered.
As the discussion wound down, it became fairly clear that the consensus was against changing how module dependencies work in live patching. The mechanism that the kernel has now, in the end, works well enough; it looks like it will not be going away anytime soon.
Other topics
Petr Mladek talked about the problems that come with modifying data structures in live patches. One has to start by locating the affected data and accesses; that is easy with a global variable, harder for data stored in multiple lists, and nearly impossible for uses that have been hidden via casts. Switching to the new values must be done carefully, once all of the code is in a position to handle them. Many techniques, such as the use of shadow structures to add data to existing structures, suffer from performance problems. And the problem of reverting a live patch gets that much harder when data changes have been made.
Miroslav Benes returned to talk about the problems associated with patching functions in the scheduler. It turns out that schedule() is a tricky function to work with, since it returns with a different stack than the one it was called with. This caused difficulties with a 2015 live patch fixing a security problem with x86 local descriptor table handling.
He outlined a solution to the problem involving putting the instruction pointer into the context that is saved when a context switch is made. That information can be used after a patch is applied to ensure that the version of schedule() that restores a given context is the same as the one that saved it. The solution is workable, but it's not clear that it matters that much; security issues in schedule() are rare and there may not be a need to apply another live patch to it anytime soon.
Jiri Kosina led a brief session on future work. The consistency model, as noted above, has been blocked for a long time on related issues. Now that the stack-validation work has been done and, hopefully, kernel-stack tracebacks can be trusted, it should be possible for that work to continue. There will likely be new proposals in that area soon.
In particular, the hybrid consistency model is likely to move forward. It should be reliable now that the stack traces are correct, but there is an associated problem: it requires a kernel built with frame pointers, and that has a significant performance cost — on the order of 10%. Nobody seems to know why turning on frame pointers hurts that badly; simply compiling the kernel with one register disabled does not have the same effect. Mel Gorman is evidently doing some benchmarking to try to track this problem down.
Kosina said that he is currently working on a port to the arm64 architecture. Beyond that, he said, there's not much point about worrying about other possible developments in live patching. The hybrid consistency model is likely to keep the group entertained for quite some time.
The microconference closed with a wide-ranging talk from Balbir Singh; much of it was taken up by low-level PowerPC details that are probably of relatively little interest to those outside the room. He did raise a few larger questions, though. One of those is expanding live patching to user-space code as well; there are, evidently, users who are interested in that capability.
He asked: what are the benefits of using live patching rather than performing a live cluster update? If a cluster can be taken down and upgraded one machine at a time, there is no real need for a live-patching infrastructure. We don't all run clusters, but users whose uptime needs make them consider live patching maybe should be using clusters.
His last question had to do with rootkits; a live-patching mechanism is obviously a nice tool by which code can be injected into a running kernel. Kosina said that he doesn't really understand what the worry is in this regard. A live patch is just a module; if an attacker can load modules into the kernel, the game is already over. But, Singh said, there could be a vulnerability in the live patch itself; this is something that has happened to other vendors in the past. Live patching is meant to be a way to quickly close security problems, but, like any other sort of patch, it always runs the risk of introducing new vulnerabilities of its own.
[Thanks to LWN subscribers for supporting our travel to the event.]
Patches and updates
Kernel trees
Architecture-specific
Build system
Core kernel code
Device drivers
Device driver infrastructure
Filesystems and block I/O
Memory management
Networking
Security-related
Virtualization and containers
Miscellaneous
Page editor: Jonathan Corbet
Distributions
Fedora on Macs, or the lack thereof
The Fedora 25 release is close, but it wouldn't be Fedora without a schedule slip or two. So it was arguably unsurprising when the November 10 "Go/No-Go meeting" concluded that this release wasn't quite ready and the release date needed to be pushed back to November 22. The reason for the delay raised some eyebrows, though, and has led to questions about what the core release criteria for Fedora should be.The problem that blocked the release, in short, is that dual-boot installations on some macOS systems fail. The root cause would appear to be in Fedora's "blivet" module, which is charged with management of the storage configuration as part of the system installation. Blivet gets confused about the nature of the partitions on the disk, causing it to try to reuse a partition that it should, due to the fact that said partition holds the macOS installation, not be touching at all. That attempt simply fails, leading to a broken Fedora installation. This result is unfortunate, but disappointed Apple users should take consolation in the fact that it could have been worse: the potential for wrecking the macOS installation was there if things had gone a little differently.
The problem, it seems, is reasonably well understood, and it is highly likely to be fixed by the next time the Fedora project gets around to deciding whether Fedora 25 is ready. But the decision to block the release raised some questions: should problems on Apple hardware be sufficient to block Fedora releases, and why did this problem only come to the fore at the end of the release cycle?
The Fedora community maintains a
set of criteria for each release specifying the things that must be
working for the distribution to be considered ready. A bug that violates
one of the criteria is thus sufficient to block a final Fedora release.
With regard to coexistence with macOS, the
relevant criterion reads simply: "The installer must be able to
install into free space alongside an existing OS X installation, install
and configure a bootloader that will boot Fedora.
" Since the
installer proved itself unable to do that, the distribution as a whole
failed to meet this criterion.
The "Go/No-Go" meeting would normally be expected to delay a release when the criteria aren't met, but it does evidently have another option: modify the criteria to alter or remove the failing item(s). The meeting log shows that this option was considered, but ultimately rejected. A working macOS install is a part of the criteria for now, but it's not at all clear that things will stay that way.
Those who would like to change the criteria are working from one core observation: the macOS installation had been broken for some time, but nobody reported the issue until the day of the meeting. That suggests that nobody was testing the release on Apple hardware. As Josh Boyer put it:
If Fedora users do not actually care about dual-boot installations with macOS, the reasoning goes, there is little point in putting effort into supporting that configuration, and little justification for delaying the release (most users of which don't have Apple hardware) for this issue. But the discussion made clear that there are at least a few interested users. So it's not clear how the project should proceed.
Some users clearly think that the core Fedora developers themselves should
be testing installations on Apple hardware. There are a few obstacles to
that, starting with the fact that the Fedora QA team at Red Hat has an Apple hardware inventory that starts
and stops at "one old Mac Mini
"; this revelation led Michael
Catanzaro to ask: "You work for a
multibillion dollar corporation where the QA team cannot afford to buy a
laptop?
"
Said corporation could probably be coaxed or embarrassed into buying such a machine, though Apple support is probably fairly low on its own set of priorities. That said, it seems that no such hardware was bought after the last Apple-related Fedora failure, which also had a lack of testing hardware as one of its causes. But, even with shiny new hardware, there would still be the matter of the time it takes to actually do the testing and use the result; Fedora, like much of the free-software community, depends on its users for the bulk of that testing.
The situation is worsened in this case because owners of the relevant hardware may well be relatively unwilling to subject it to testing that could destroy the contents of the system. Apple's licensing also make testing in virtual machines impossible in the absence of Apple hardware. So this particular configuration may always be under-tested relative to others. Apple's lack of interest (to put it gently) in encouraging Linux on its hardware also doesn't help.
As a result, the Fedora project is having to consider whether it can realistically support Apple hardware going forward. And things might not stop there; Adam Williamson has let it be known that he will be looking at other release criteria as well:
Development projects rarely want to remove useful features from the list of things they support, for obvious reasons. In this case, some Fedora developers, at least, feel that Apple hardware support is an important way to bring in new users. But a failed installation is a certain way to put off potential new users, so, if Fedora wants to support this hardware, then some people, somewhere, are going to have to step up and help to test it. Free-software communities cannot be successful without broad testing; Fedora is no different from any other in that regard.
Brief items
Distribution quotes of the week
openSUSE Leap 42.2
The openSUSE Project has announced the release of openSUSE Leap 42.2. "Leap is made to give stability-minded users and conservative technology adopters peace of mind. openSUSE Leap 42.2 is powered by the Linux 4.4 Long-Term-Support (LTS) kernel and is a secure, stable and reliable server operating system for deploying IT services in physical, virtual or cloud environments." See the features page for details.
Oracle Linux 7.3 Available Now
The Oracle Linux and Virtualization Team has announced the general availability of Oracle Linux 7 Update 3. "This is the first Oracle Linux 7 ISO to include UEK Release 4 (UEK R4). Please note that new installations of Oracle Linux 7 Update 3 will install and boot the UEK R4 kernel by default. However, updates to existing Oracle Linux 7 environments require the user to explicitly install UEK R4 and will not automatically replace existing UEK R3 kernels."
Distribution News
Other distributions
Discontinuing Software Collections for Scientific Linux
Scientific Linux will be discontinuing the Software Collections. The existing RPMs will be archived. Packages that were available in Software Collections are now available at SoftwareCollections.org.
Newsletters and articles of interest
Distribution newsletters
- DistroWatch Weekly, Issue 687 (November 14)
- Linux Mint Monthly News (November)
- Lunar Linux weekly news (November 11)
- openSUSE news (November 10)
- openSUSE Tumbleweed – Review of the Week (November 11)
- Tails report (October)
- Ubuntu Weekly Newsletter, Issue 487 (November 13)
Fedora 25 to have MP3 playback
Christian Schaller writes that, after all these years, a stock Fedora system will be able to play MP3 files. "I know this has been a big wishlist item for a long time for a lot of people so I am really happy that we are finally in a position to fulfill that wish. You should be able to download the mp3 plugin on day 1 through GNOME Software or through the missing codec installer in various GStreamer applications. For Fedora Workstation 26 I would not be surprised if we decide to ship it on the install media."
Page editor: Rebecca Sobol
Development
Python context managers
If you have been programming for a while now, you might have dealt with issues related to databases, network sockets, files, and so on, which are often called resources. To understand what we mean by resources, think of anything that is both useful and in limited supply. The main feature of resources and, in particular, their limited availability is that once you finish using them they have to be returned back to the system. Failure to do so can result in various problems, one of which is a memory leak, meaning that memory is allocated but not freed. Context managers in Python can help with resource handling.
The underlying issue is what's called resource management. This
includes any task that the programmer or the Python interpreter needs to
carry out to make sure that any resource that has been used is returned
back to the system. Let's look at an example to clarify this further. Say you have created a
new database mydb, with one table Person, that
contains three fields (columns) ID, Name,
Age, as follows:
import sqlite3
connection = sqlite3.connect('mydb.db')
connection.execute('''CREATE TABLE PERSON
(ID INT PRIMARY KEY NOT NULL,
NAME TEXT NOT NULL,
AGE INT NOT NULL);''')
connection.close()
Assume that some exception occurred when running the
execute() method. In this case, the database connection
will never be closed, eventually leading to a memory leak. If a
similar script was part of a function that gets called frequently (i.e. a
query in a web server), the situation could be particularly problematic.
We can thus conclude that this wouldn't be the best way to implement
this kind of function. A good solution to this is to handle the
exceptions in order to close the database connection even when an
exception has occurred. This could be done using the
try/finally clause:
try:
connection.execute('''CREATE TABLE PERSON
(ID INT PRIMARY KEY NOT NULL,
NAME TEXT NOT NULL,
AGE INT NOT NULL);''')
finally:
connection.close()
Although the try/finally clause solves the
problem, it still raises some questions, such as whether we need to make
another outer try/finally clause to catch an
exception that was raised by sqlite3.connect(). If we need to make
such outer try/finally clauses, we will surely
end up with messy code. There must be a better solution.
Context managers can be part of that solution. They wrap a block of code and ensure that specific operations are performed before and after it. In other words, a context manager will be responsible for a resource within the code block such that it ensures the resource is created when the block is entered, and cleaned up when the block is exited.
Context managers were first introduced more than
ten years ago,
in Python 2.5, by Guido van Rossum and Nick Coghlan. PEP 343 added a
new keyword to the language, with, that enables context
managers. Thus, when using the
with statement, we are actually entering a context
manager.
Context manager syntax
The with statement works much the same way as
try/finally blocks, but with a cleaner
syntax. Based on Python's
documentation:
Using a context manager has the following syntax:
with expression [as variable]:
some_code
The expression produces a context manager object,
while the variable refers to the object returned by the context
manager's __enter__() method (more on this in the next
section). Let's rewrite the above script using a context manager. It could
look as
follows:
import sqlite3
with sqlite3.connect('mydb.db') as connection:
connection.execute('''CREATE TABLE PERSON
(ID INT PRIMARY KEY NOT NULL,
NAME TEXT NOT NULL,
AGE INT NOT NULL);''')
Inner workings
In the above context manager, the with statement will
evaluate the sqlite3.connect() expression, resulting in an
object known as a context manager that defines
two special methods: __enter__() and
__exit__(). The __enter__() method is called when
a context manager is created in a with statement, returning a
result that is assigned to the variable after the as
keyword. The __exit__() method, on the other hand, is called
when the context manager goes out of scope after the with
statement. The object returned by the
sqlite3.connect() function is a
database connection object that implements the context manager protocol.
Notice that we don't need to use a finally block with
context managers, since they are guaranteed to execute the
__exit__() method. If we are working with files, for instance,
the __exit__() method always guarantees that the file is
closed if it was opened.
The prototypes for __enter__() and __exit__() are as follows:
def __enter__(self):
def __exit__(self, type, value, tb):
The __enter__() method runs immediately when the
expression is evaluated. The __exit__() method
is called with four arguments when the context manager goes out of scope:
self, an exception type, an exception instance, and a
traceback object. If
there are no exceptions within the block, all the arguments (excluding
self) are set to None.
Say we want to define a class where its instances act as context managers, we can do the following:
class MyFile():
def __init__(self, file_name, mode):
self.file_name = file_name
self.mode = mode
def __enter__(self):
self.open_file = open(self.file_name, self.mode)
return self.open_file
def __exit__(self, type, value, tb):
self.open_file.close()
Using the context manager, we can write:
with MyFile('foo.txt', 'w') as file:
file.write('foo')
The above context manager will simply create a file named
foo.txt, and write the word foo to that
file. When the with block is exited, the __exit__()
method will ensure that the file gets closed.
Why use context managers?
Context managers are mainly used for managing
resources. For instance, when we open a file we are consuming a
resource called a file descriptor, that is an integer handle
assigned by the operating system to refer to an I/O channel
(i.e. file). Context managers make sure that any opened file is also
closed, since
there is a limit on the number of open files a process can have at one
time. The command ulimit -n can show you the number of those
files. In my case it is 256 files.
Trying to always remember adding a close() function after
each open() is not an easy task, especially if the file was
located in a complicated function that has multiple return paths or can raise
exceptions. Thus, context managers guarantee that cleanups always happen.
Nested context managers
The with statement can have nested (multiple) context
managers that can be separated by commas. Nested context managers can be
written in the following different ways:
with M() as m, N() as n:
code
or:
with M() as m:
with N() as n:
code
It is important to note here that the __exit__()
functions for both context managers will run when the statement block exits.
contextlib module
The contextlib
module contains utilities for creating context managers. Let's take an
example that uses
contextlib.closing(), which will ensure that the object passed
to it is closed, to clarify that further.
Let's say we want to open some web page and print the lines of that
web page, we can do the following:
import contextlib
import urllib.request
url = 'http://abder.io/'
with contextlib.closing(urllib.request.urlopen(url)) as webpage:
for line in webpage:
print(line)
Here, when the with statement runs, the
contextlib.closing()
helper creates a context manager on the fly to ensure that the URL
object gets closed.
It is important to note that using
contextlib.closing() replaces the need to define both the
__enter__() and __exit__() methods.
Conclusion
Context managers come in handy to manage resources
in Python, because the __exit__() method is always guaranteed
to execute and can clean ensure that those resources are cleaned up. The
contextlib module contains helpers
for creating context managers. It is worth considering reaching for the
context manager tool when building your next Python application.
Brief items
Development quotes of the week
We’re approaching a time where software will drive the vehicle that transports your family to soccer practice. There are already AI programs that help doctors diagnose disease. It’s not hard to imagine them recommending prescription drugs soon, too.
The more software continues to take over every aspect of our lives, the more important it will be for us to take a stand and ensure that our ethics are ever-present in our code.
Since that day, I always try to think twice about the effects of my code before I write it. I hope that you will too.
Firefox 50.0
Mozilla has released Firefox 50.0. This version features improved performance for SDK extensions or extensions using the SDK module loader, added download protection for a large number of executable file types, added option to Find in page that allows users to limit search to whole words only, and more. See the release notes for details.Announcing Rust 1.13
Rust 1.13.0 has been released. "The 1.13 release includes several extensions to the language, including the long-awaited ? operator, improvements to compile times, minor feature additions to cargo and the standard library. This release also includes many small enhancements to documentation and error reporting, by many contributors, that are not individually mentioned in the release notes. This release contains important security updates to Cargo, which depends on curl and OpenSSL, which both published security updates recently."
xorg-server 1.19.0
X.Org Server 1.19 has been released. This version features threaded input support, XWayland improvements, modesetting driver improvements, and more.
Newsletters and articles
Development newsletters
- Emacs News (November 14)
- These Weeks in Firefox (November 16)
- What's cooking in git.git (November 9)
- What's cooking in git.git (November 11)
- What's cooking in git.git (November 16)
- Git Rev News (November 16)
- GNU Toolchain Update (November)
- This week in GTK+ (November 14)
- OCaml Weekly News (November 15)
- Perl Weekly (November 14)
- Python Weekly (November 10)
- Ruby Weekly (November 10)
- This Week in Rust (November 15)
- Wikimedia Tech News (November 14)
Page editor: Rebecca Sobol
Announcements
Brief items
Microsoft joins The Linux Foundation
The Linux Foundation has announced that Microsoft has joined as a platinum member. "From cloud computing and networking to gaming, Microsoft has steadily increased its engagement in open source projects and communities. The company is currently a leading open source contributor on GitHub and earlier this year announced several milestones that indicate the scope of its commitment to open source development."
The Linux Foundation's Core Infrastructure Initiative Renews Funding for Reproducible Builds Project
The Core Infrastructure Initiative (CII) has announced continued financial support for the Reproducible Builds Project. "The grant extends the contribution to include Debian developers Chris Lamb, Mattia Rizzolo, Ximin Luo and Vagrant Cascadian, as well as extending funding for Holger Levsen. Furthermore, this contribution adds support for Ed Maste, working with FreeBSD." (Thanks to Paul Wise)
Farewell to Rob Collins
The EuroPython Society shares the sad news that Rob Collins has passed away. "Many of you may know Rob from the sponsored massage sessions he regularly ran at EuroPython in recent years and which he continued to develop, taking them from a single man setup (single threaded process) to a group of people setup by giving workshops (multiprocessing) and later on by passing on his skills to more leaders (removing the GIL) to spread wellness and kindness throughout our conference series."
Articles of interest
FSFE: Russian Bill makes Free Software a Public Priority
The Free Software Foundation Europe covers a bill that will boost Free Software on multiple levels within the Russian Federation's public sector. "The draft, approved by the Russian Federation's Duma (lower chamber) in mid-October, requires the public sector to prioritise Free Software over proprietary alternatives, gives precedence to local IT businesses that offer Free Software for public tenders, and recognises the need to encourage collaboration with the global network of Free Software organisations and communities."
New Books
Wicked Cool Shell Scripts, 2nd Edition--new from No Starch Press
No Starch Press has released "Wicked Cool Shell Scripts, 2nd Edition" by Dave Taylor and Brandon Perry.
Calls for Presentations
PGConf India 2017 - Call for Papers
India PostgreSQL User Group has announced that PGConf India 2017 will be held in Bengaluru on March 3, 2017. The call for papers deadline is December 31. "If you are doing something interesting with PostgreSQL, please submit a proposal. You might be one of the backend hackers or work on a PostgreSQL related project and want to share your know-how with others. You might be developing an interesting system using PostgreSQL as the foundation. Perhaps you migrated from another database to PostgreSQL and would like to share details. These, and other stories are welcome. Both users and developers are encouraged to share their experiences."
CFP Deadlines: November 17, 2016 to January 16, 2017
The following listing of CFP deadlines is taken from the LWN.net CFP Calendar.
| Deadline | Event Dates | Event | Location |
|---|---|---|---|
| November 18 | February 18 February 19 |
PyCaribbean | Bayamón, Puerto Rico, USA |
| November 20 | December 10 December 11 |
SciPy India | Bombay, India |
| November 21 | January 16 | Linux.Conf.Au 2017 Sysadmin Miniconf | Hobart, Tas, Australia |
| November 21 | January 16 January 17 |
LCA Kernel Miniconf | Hobart, Australia |
| November 28 | March 25 March 26 |
LibrePlanet 2017 | Cambridge, MA, USA |
| December 1 | April 3 April 6 |
‹Programming› 2017 | Brussels, Belgium |
| December 10 | February 21 February 23 |
Embedded Linux Conference | Portland, OR, USA |
| December 10 | February 21 February 23 |
OpenIoT Summit | Portland, OR, USA |
| December 31 | March 2 March 3 |
PGConf India 2017 | Bengaluru, India |
| December 31 | April 3 April 7 |
DjangoCon Europe | Florence, Italy |
| January 1 | April 17 April 20 |
Dockercon | Austin, TX, USA |
| January 3 | May 17 May 21 |
PyCon US | Portland, OR, USA |
| January 6 | July 16 July 23 |
CoderCruise | New Orleans et. al., USA/Caribbean |
| January 8 | March 11 March 12 |
Chemnitzer Linux-Tage | Chemnitz, Germany |
| January 11 | February 15 February 16 |
Prague PostgreSQL Developer Day 2017 | Prague, Czech Republic |
| January 13 | May 22 May 24 |
Container Camp AU | Sydney, Australia |
| January 14 | March 22 March 23 |
Vault | Cambridge, MA, USA |
If the CFP deadline for your event does not appear here, please tell us about it.
Upcoming Events
Events: November 17, 2016 to January 16, 2017
The following event listing is taken from the LWN.net Calendar.
| Date(s) | Event | Location |
|---|---|---|
| November 13 November 18 |
The International Conference for High Performance Computing, Networking, Storage and Analysis | Salt Lake City, UT, USA |
| November 14 November 18 |
Tcl/Tk Conference | Houston, TX, USA |
| November 16 November 17 |
Paris Open Source Summit | Paris, France |
| November 16 November 18 |
ApacheCon Europe | Seville, Spain |
| November 17 | NLUUG (Fall conference) | Bunnik, The Netherlands |
| November 18 November 20 |
GNU Health Conference 2016 | Las Palmas, Spain |
| November 18 November 20 |
UbuCon Europe 2016 | Essen, Germany |
| November 19 | eloop 2016 | Stuttgart, Germany |
| November 21 November 22 |
Velocity Beijing | Beijing, China |
| November 24 | OWASP Gothenburg Day | Gothenburg, Sweden |
| November 25 November 27 |
Pycon Argentina 2016 | Bahía Blanca, Argentina |
| November 29 November 30 |
5th RISC-V Workshop | Mountain View, CA, USA |
| November 29 December 2 |
Open Source Monitoring Conference | Nürnberg, Germany |
| December 3 | NoSlidesConf | Bologna, Italy |
| December 3 | London Perl Workshop | London, England |
| December 6 | CHAR(16) | New York, NY, USA |
| December 10 | Mini Debian Conference Japan 2016 | Tokyo, Japan |
| December 10 December 11 |
SciPy India | Bombay, India |
| December 27 December 30 |
Chaos Communication Congress | Hamburg, Germany |
If your event does not appear here, please tell us about it.
Page editor: Rebecca Sobol
