/var/log/andrey     About     Archive     Feed

PID file safety

There are some instances where we need to use the old-style PID files in order to signal a daemon process (typically sending it a SIGHUP to ask it to re-read its configuration files or a SIGTERM to ask the daemon to exit). We can get our of the business of managing daemons with things like systemd but in the cases when we still have to deal with PID files, we should be careful.

Typically we have opened a PID file for a hypothetical daemon, food:

FILE *f = fopen("/var/run/food.pid", "r");
if (f) {
    /* Daemon may be running. */

We then need to read in the PID (we expect the file to contain just a number) so we can send that daemon a signal. This can be as simple as:

pid_t pid;
if (fscanf(f, "%" SCNiMAX, &pid) == 1) {
    /* We probably read a PID */

It’s very important that we check the result of fscanf(3) as we only want to proceed if we read something that looks like a number. kill(2) is very dangerous depending on what we do with it and what our privileges are on the system. For instance, the pid argument to kill implies:

  • Send the signal to every process that we have permission to if pid is -1, certainly this would be bad. If pid is less than -1, the signal will be sent to a particular process group.
  • Send the signal to every process in the process group of the calling process if pid is 0, this is also bad.
  • If pid is positive, send the signal to that process. However if pid is 1, we are going to send that process to the init system. If pid happens to be our own PID, we send the signal to ourselves.

The data type for a PID is pid_t which in the GNU standard C library is an int. We should probably check that the PID at least looks like something sane:

pid_t pid;
if (fscanf(f, "%" SCNiMAX, &pid) == 1 && pid > 1 && pid != getpid()) {
    /* We probably read a PID and it seems sane */

Depending on the application, we may also use getppid(2) to make sure the PID is not the one for our own parent process.

We can then try to check if someone is running with that PID. Traditionally that is done by sending a 0 signal (a 0 signal means that no signal is actually sent but error checking is still performed).

fclose(f);

if (kill(pid, 0) == -1) {
    if (errno == ESRCH) {
        /* Nothing with that PID seems to exist
           (or the process is a zombie) */
    } else if (errno == EPERM) {
        /* We don't have permissions to send a signal
           to this process */
    }
} else {
    /* We can send signals to this PID, proceed,
       for example: */
    if (kill(pid, SIGHUP)) {
        fprintf(stderr, "Couldn't signal %d: %m", pid);
    }
}

Finally, if we need to implement the daemon side (double-forking, closing file descriptors, optionally creating PID files, and so on) please consider linking against libdaemon rather than writing the code yourself (see the testd.c example for usage).

Opening files (and Linux drivers)

We should be careful (if not downright paranoid) when opening files. Some of the recommended checks to perform and best practices include:

  • Using realpath(3) to produce a canonicalized absolute path for us when the path comes from outside.
  • Setting O_CLOEXEC to make sure that the file descriptor is not leaked to any child processes we spawn
  • Sanity-checking the file with fstat(2) to make sure it looks like the kind of file we are expecting

When appropriate, we can also use the fstat(2) output to check for:

  • Expected file ownership (at least with the st_uid and st_gid), for example if we expect a specific user and/or group to own the file, regardless of our ability to access it.
  • An expected physical location (st_dev field), for example if we expect it to reside on a specific disk or device regardless of what the path says.
  • Expected permissions (st_mode field), for example we may want to refuse to open an executable file or a file with too lax of permissions no matter what

The path

A program taking a path from the outside world, for example through a command line argument, should sanitize the path (per CERT FIOO2-C). Typically this looks like:

int main(int argc, char **argv)
{
    if (argc < 2) {
        printf("Usage: %s <path>\n", argv[0]);
        exit(EXIT_SUCCESS);
    }

    char *path = realpath(argv[1], NULL);
    if (!path) {
        fprintf(stderr, "Invalid argument: %m");

The resolved path will need to be freed.

Example: Talking to a SPI (spidev) device

We can now try to open the file given the resolved path, however we should sanity-check that the file looks like something that we expect to open. For example, a SPI device interfaced via the Linux spidev driver should at least:

  • Be a character device (and not, say, a regular file or socket)
  • Have the major 153

We specifically want to use fstat(2) rather than stat(2) because we want to be sure that we are checking the file we opened rather than checking a path twice (and allowing whatever the path resolves to to change out from under us).

First, we open the file:

int fd = open(path, O_CLOEXEC);
if (fd == -1) {
    fprintf(stderr, "Unable to open \"%s\"\n", path);
    goto out_fd;
}

Then we perform some basic sanity checks. The st_mode field tells us what kind of file we have and there are convenient macros to simplify our checks: ST_IS_CHR checks that this is a character device, which is what we expect. In order cases we may want a regular file (S_ISREG matches that).

For character devices and other special files we also have the st_rdev field on which we can use macros major and minor to check for specific IDs.

struct stat st;
if (fstat(fd, &st) || !S_IS_CHR(st.st_mode) || major(st.st_rdev) != 153) {
    fprintf(stderr, "\"%s\" does not look like a SPI device\n", path);
    goto out_st;
}

We have now opened the file and reasonably believe that it is a SPI device. Our cleanup would be in reverse order:

out_st:
    close(fd);
out_fd:
    free(path);

or the GCC cleanup attribute can be used to clean up resources.

Using spidev with the Linux kernel device tree

I recently hit a WARN_ON when adding a spidev device to a device tree, the warning is:

buggy DT: spidev listed directly in DT

and it was introduced by this patch. This is quite unfortunate but easy to work around, though I would argue that it’s counter to the point of the spidev driver to begin with: after all we’re describing hardware that we’re talking to from user space and there’s no need to describe it in the device tree, this just creates extra work.

Solution 1: the proper way

To avoid this warning you will need to add your device to the spidev_dt_ids table in drivers/spi/spidev.c and then use that device string (and not literally spidev in your device tree compatible). For example you could add a device named foocorp,modem to the end of that table:

--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -695,6 +695,7 @@
 static const struct of_device_id spidev_dt_ids[] = {
	{ .compatible = "rohm,dh2228fv" },
	{ .compatible = "lineartechnology,ltc2488" },
+	{ .compatible = "foocorp,modem" },
	{},
 };
 MODULE_DEVICE_TABLE(of, spidev_dt_ids);

And then your device tree entry would contain a node with the corresponding compatible string:

compatible = "foocorp,modem";

When the spidev module is probed, things should match up and you will see a corresponding character device as before.

Problems with this

This has some obvious problems including:

  • We now have to patch the kernel to add a string to some code for no apparent reason other than “correctness” of the device tree.
  • This patch is probably not going upstream because it’s unlikely that anyone else has this hardware (though in some cases it may go upstream).
  • Maintaining this patch is not going to be pleasant: you’re adding an entry to a table and rebasing will take some work once people add more things to that table.

Solution 2: quick and dirty

You can forgo patching the driver and simply claim one of the already included devices from the table. It’s not going to make any difference: spidev will match that string and move on. So for example I don’t have a “rohm,dh2228fv” on my board so I could have:

comptabile = "rohm,dh2228fv"; /* actually my foocorp modem */

And things will work fine and I won’t see the nasty WARN_ON anymore.

A nicer future change would be to move this spidev_dt_ids table out to the device tree itself and avoid this altogether but no one has done that yet (at least as of the 4.8 kernel). A cursory glance through arm/boot/dts shows many users of spidev that will now be seeing the WARN_ON message.

TFTP server on Fedora

Here are some quick notes on setting up a TFTP server on Fedora 23. This is used, for example, to send Linux kernel images and other binaries to a bootloader on an embedded system.

First, install the packages:

sudo dnf install -y tftp tftp-server

The tftp itself will allow you to test your configuration by attempting a file transfer. The default directory for TFTP transfers is /var/lib/tftpboot.

The TFTP server works through xinetd so you will need to add a rule that says in.tftpd: ALL to /etc/hosts.allow:

sudo su -c "echo 'in.tftpd: ALL' >> /etc/hosts.allow"

Enable and start the TFTP server:

sudo systemctl enable tftp
sudo systemctl start tftp
sudo systemctl daemon-reload

Tell the firewall to allow TFTP traffic:

sudo firewall-cmd --permanent --add-service tftp
sudo firewall-cmd --reload

You should now be able to transfer files via TFTP.

Mercedes W124 E320 Wagon notes

Here are some notes about Mercedes W124 wagon ownership in case the information is useful to other people. Specifically my experience is with the later E320 wagon (with the DOHC m104 3.2L six).

The Mercedes W124 is a fantastic car and I highly recommend it to anyone who can handle (and enjoys) doing basic maintenance and repairs themselves. They are not, however, for the faint of heart or for people who need a shop or dealer to repair everything on the car – these are somewhat complex cars with a few potential issues and repairs could get expensive unless you are willing to research and do a few things yourself, including tracking down used parts when needed.

The E320 is solid, safe, and quite reliable. The wagon portion is really well designed for doing wagon things:

E320 Wagon

The rear seats fold forward nicely in two sections and latch flat into the floor, there is a removable cargo cover and cargo net system included, and the car even provides two rear-facing seats in the back and is technically able to seat seven people when needed. The included roof rack works well and is easy to adjust. The wagons feature a hydraulic self-levelling rear suspension that handles heavy loads brilliantly.

E320 Wagon Seats Folded

The car itself drives better than the popular W123 wagon: it is much more modern, more comfortable, and smoother. The wagon door provides a soft-close mechanism much like the W140 S-class trunk latch, and the W124 has quite a lot more power of course. The later ones have very good brakes (with four piston front calipers), ABS is standard, and a rudimentary traction control system called ASR was an option.

All W124s have a driver side air bag and later (1994 and 1995) cars have a front passenger side air bag. This was added by taking away the glove box because Mercedes did not want to redesign the dashboard for the two final years. The center console does have a storage compartment and the front doors have reasonable storage as well.

Keep in mind that these cars do not have particularly good fuel economy and they do require premium (91 octane or higher) fuel. The m104 six provides about the same fuel economy as the 4.2L m119 V8 in the E420 sedan. It may be the sheer weight of the car plus the 4-speed automatic. Even freeway fuel consumption is not that great.

Our car

The W124 wagon we wound up buying is a 1994 E320 with, as it turns out, nearly all of the options. Some of the interesting ones include:

  • leather seats (the other option is vinyl)
  • heated front seats with memory (look for heater switches on either side of the center console ashtray)
  • adjustable steering column
  • headlight washer and wiper system
  • ASR (traction control)

All of the US-market wagons (I believe) have the power sunroof standard along with the rear-facing fold-out seats and cargo cover system. The standard wood trim is zebrano (zebra wood) like on the W123 but there is also an optional burl walnut trim.

Trailer Hitch

We use our E320 wagon to tow a Scamp 13-foot trailer. Curt Manufacturing makes a compatible trailer hitch kit that I combined with a generic trailer harness wiring kit. There is not much to the installation beyond following the Curt instructions and the wiring is relatively simple: I ran a fused 12V wire from the battery positive, following some brake lines to the rear of the car, then tapped into the tail light harness behind the spare tire. I removed the rear gray “glove box” trim to get to a rubber plug where the harness comes down to the hitch and also to run one wire over to the passenger side tail light turn signal wiring. The wire colors were:

  • tail lamp: gray/black or gray/red
  • brake: black/red
  • left turn signal: black/white
  • right turn signal: black/green

E320 Wagon With Camper

Issues and Things to Avoid

There are a number of potential problems or weak points on the W124. They are easy enough to deal with but it is important to be aware and ready.

4Matic

The W124 has the first implementation of 4Matic and it is extremely complex and trouble-prone, plus parts to repair it are difficult to obtain. Just avoid the the 4Matic-equipped 300TE or stick with the E320 which was not offered with 4Matic in the US. This wikipedia article explains 4Matic.

Transmission

The 4-speed automatic in these cars is a Mercedes design and is very reliable for an automatic. Most used W124 cars are likely to have enough miles on them to need a transmission rebuild. A replacement transmission runs about $2500 at this time which given the low cost of the car to begin with is not really that big of a deal. You may be able to find a car that already has a new or rebuilt transmission, that is definitely a bonus. The previous owner of our E320 had the transmission replaced at about 200,000 miles.

These transmissions can fail in a number of ways but a typical warning sign is difficulty in engaging reverse: if that is happening, a transmission rebuild is coming soon. A car without working reverse definitely needs a transmission.

Wiring

The W124 wagons were made during the range of years in which Mercedes had a huge problem with wiring harness insulation. The later-model E320 cars like ours will absolutely have the “wiring problems” so it’s important to know what harnesses have already been replaced when looking at used cars. There are actually several wiring harnesses under the hood that can (and will) fail, I think the total is four separate units if you count the throttle body.

The first one to check is the main fuel injection wiring harness. This starts at the ECU (behind the battery) and runs to the engine (between the valve cover and the intake manifold), connecting to the MAF, all injectors, and various sensors on the front of the engine. This harness is very expensive ($1400 or so new) but it can be replaced with a used one that was built after the wiring insulation was improved – the key is the date code on the harness.

The fuel injection harness date code can be found near where the harness plugs into the ECU. To see it open the hood (all the way up via the vertical latches helps) and remove the plastic ECU cover behind the battery (it’s just stuck into place, no fasteners). You should hopefully see a white Delphi parts tag with a date code much newer than the year of the car on this harness, indicating a replacement part. A date code near the car’s production date or model year likely indicates the original part and this harness is very likely to fail soon if it hasn’t already.

Another harness connects to the alternator and starter (this actually failed on ours) but is much harder to inspect.

Finally, these cars have a partially drive-by-wire (electric) throttle body. The wiring in the throttle body has the same insulation problem as the fuel injection harness and will fail. A good warning sign (and our E320 had this) is non-functional cruise control. The throttle wiring may still fail even if the cruise control works but a non-functional cruise control tells you that this is likely the case. Again this throttle can simply be replaced with one from a newer car (Mercedes used the m104 motor for several more years), I used one from a newer C-class with a 2003 date code to repair our 1994 E320 and it worked perfectly. The wiring can also be repaired via a mail-in service offered by a couple of companies (that will run around $400 or so from what I have read). The throttle does have a date code noted on a parts sticker but it may be very difficult to see without taking things apart.

There are two variants of the E320 throttle body (and corresponding idle/throttle control ECU) – one for cars with ASR and another for cars without ASR. They are not interchangeable.

Engine

The m104 six is considered very reliable, however they are known to have a weakness in the head gasket and eventually may develop an oil leak toward the back of the head. Blown head gaskets are not unheard of as well. Our E320 has well over 226k miles on it and runs fine though (we do not have any records indicating a rebuild or even a new head gasket but maybe it was done at some point).

Other Issues

The m104 motors have a less than ideal EGR tube design and these tubes can get clogged due to a nearly 90-degree bend. I personally have not experienced this problem but the solution is to clean the tube or replace it with a newer design part.

Some owners install an off-brand MAF sensor while troubleshooting the car (or when the MAF genuinely fails). These are known to be junk and indeed my car came with some off-brand MAF that soon failed. The correct Bosch MAF is very expensive however I was able to find a cheap used one on eBay and it works fine.

The W124 relies on vacuum to control several subsystems including the HVAC so make sure that all the dashboard controls are working (note that the top center vents are not used when heating, that is by design) since that system is hard to troubleshoot. The power locks and wagon hatch lock are also vacuum-actuated.

The self-levelling rear suspension is very reliable but, when it fails, requires a more expensive set of parts than a traditional gas shock absorber. I cannot think of a good way to check this system beyond obvious signs of hydraulic leaks, however I am told that the rear suspension will feel rock-hard and uncomfortable (little to no dampening) when it fails. I did get to see ours work in an obvious way several times but that would be hard to do on a test drive: load the wagon with a lot of heavy things (in my case, hundreds of pounds of tile for a bathroom remodel) and then start the car and watch the rear end lift to the right ride height.

I have heard of W124 wagons with leaks in the wagon back area, probably from the hatch itself or one of the side windows. This can result in significant damage or rust so it’s worth checking for. Ours seems to be leak-free.

The rear wagon door hatch struts eventually fail. Replacements aren’t very expensive and you can install them yourself with a bit of effort (not my favorite repair job, but I got through it!) to restore operation. The door is very heavy otherwise.

The W124 is one of the last (if not the last) cars to use the “bullet” (rather than “blade”) fuses that were popular on German cars. There are two kinds of “bullet” fuses: ones with a silver color contact and ones with a copper color contact. The original silver ones are known to build up resistance and cause circuits to act like they are open (that is, the fuse is blown but it is not physically blown), causing all sorts of problems. All of the fuses should be replaced with the copper ones. For example we once noticed that the power seats and wipers stopped working: replacing the corresponding fuse solved the problem immediately even though that (silver color contact) fuse was not blown.

comments powered by Disqus