43 comments

[ 3.1 ms ] story [ 98.7 ms ] thread
Make a game of it: How many random bytes can you write (to random locations) before (your program | the entire system) goes badly awry or unresponsive?
This is pretty tangential but seeing this reminds me of the days when the puredyne distro used to pipe /dev/mem to /dev/dsp as a noisy startup chime.
If you had lots of ram this may have taken a while. In grad school we piped vmlinux and other files to /dev/dsp as a crude acoustic "tripwire" to "listen" to the system configuration.
I think we need to examine the definition of "pipe" in a POSIX context here. Pipelines feed the output of one program into the input of another one. You don't "pipe" files, you copy them.
(comment deleted)
Talk about a memory leak.
(comment deleted)
I remember piping /dev/mouse (or whatever) to /dev/dsp to make noises when the mouse moved. Good times.
I did that for some pics too, kinda funky to have actual memory map
Not super related but a pleasantly surprising linux /dev trick I discovered yesterday was piping “hello” to /dev/udp/<ip>/<port> in order to check connectivity between two machines (the other was listening using nc)
To be pedantic, that’s provided by bash, not devfs. You wouldn’t be able to do it like this from e.g. a C program.
You mean that bash interprets the path and creates the socket itself?
Yes, bash does that. It's a bash feature:

https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash....

> Bash handles several filenames specially when they are used in redirections, as described in the following table. If the operating system on which Bash is running provides these special files, bash will use them; otherwise it will emulate them internally with the behavior described below.

> ...

> Bash attempts to open the corresponding [...] socket.

Even more fun is that if you create /dev/udp/127.0.0.1 (and chmod a+rwx), it won't create the file 53 if you "echo hello > /dev/udp/127.0.0.1/53". Instead it sends a UDP packet to your DNS server.

If you create a symlink to a path like /dev/udp/127.0.0.1/53 and redirect output to the symlink, a packet is not sent; the file is written as normal.

I'm guessing nobody has ever actually had a problem with this, so it's not actually a bad design choice, but I personally wouldn't have written that code. Leaky abstraction.

I dunno, if you “echo foo > /dev/null” then “cat /dev/null” you won’t get foo back. Plenty of assumptions about filesystem behaviour don’t work in all cases.

That being said, I’d prefer if the symlink actually worked and sent the packet.

(comment deleted)
Yeah when I was testing it, I definitely half-expected the symlink to work.

I will quibble with you on /dev/null a little bit. /dev/null works like any other file; there is absolutely no guarantee that you can read what you wrote on any filesystem write on UNIX. You can "echo foo > regular_file" and then "cat regular_file" and it could be gone or have completely different content. Other processes writing the file, network filesystems, quantum rays, who knows. So to me, /dev/null is not unusual in that respect at all, except that that probability function that you can read what you wrote looks a little different than a regular file.

Most importantly, /dev/null isn't a construction implemented by bash. Any program on the OS sees the same behavior as your shell script. That said, this isn't really as unusual as I originally thought. You can open a file named $HOME/foo in bash and that's going to be a very different file in your C program. I do like the $ to indicate "hey this is a quirk of the programming language that's allowing this", though.

That’s probably because bash is only looking for those types of paths in a redirection context. But if you try to use regular file utilities those paths don’t have any special meaning so they just work as normal.
I think this was a design mistake. If they wanted to come up with a new syntax for sending UDP packets, fine.

If they persuaded the kernel devs to make some devfs way that those were real files, using the unix filesystem API, also fine.

But making something that looks like a real thing in the filesystem, but isn't usable by other programs that use the filesystem... Thats not right.

This is also handy for directly accessing memory that's been mapped in from peripherals and special-purpose processors. Though it might not always work because of clock gating.
I'm surprised access through /dev/mem happens below the caching layer. I wouldn't have even thought of that possibility. Any idea why that is?
A very common usage for /dev/mem is to access a device through memory mapped IO from user space.

Cacheable accesses would break that use case.

If my memory serves me correctly you can control the mapped caching attributes using file flags, like O_SYNC, etc. Might also be architecture dependent. If you want to manipulate a memory-mapped device then you don't want caching, but if you want to see memory the same way a typical application does, then you want to keep the caching attributes in your mapping. It's a low-level tool, so there is no right or wrong really.
...it's memory. Where would you cache memory access, in other memory ?

CPU got cache for caching memory

Exactly - the article says "the memory might be cached by the CPU which possibly incurs cache coherence problem".

I would expect the memory access to happen through the CPU and its cache, avoiding such problems.

The 'devmem' command is pretty neat when doing embedded systems, allowing you to write entire device drivers in bash!
That's a horrible idea. You should use javascript instead.
if you aren't using Lisp, then are you even a real driver developer?
I've done this. It was fun. PiFM was developed this way.
Isn't this a security risk?
- `/dev/mem` should only be accessible by root or whoever you set the permissions to (don't `chmod 777 /dev/mem`).

- root can install device drivers which have full executable run of the system anyway and do anything you can do with this device; this is also true on Windows.

- read about CONFIG_STRICT_DEVMEM - https://man7.org/linux/man-pages/man4/mem.4.html#:~:text=Sin....

- wait until you hear about `/dev/kmem`.

- it's possible to build a Linux kernel without `/dev/mem` support and also without loadable module support (I think), so if your threat model indicates this needs to be addressed it is possible.

It would be a fun exercise/YouTube video/class… you are an unprivileged user, /dev/mem is 777, go forth and prosper.
(comment deleted)
`CONFIG_LOCK_DOWN_KERNEL_FORCE_CONFIDENTIALITY=y` or similar may also be of interest, see `man kernel_lockdown`.
>root can install device drivers which have full executable run of the system anyway and do anything you can do with this device; this is also true on Windows.

Oddly enough, no. Or atleast last time I tried on Ubuntu I had to disable secure boot. Seemed like an easier way than to sign the build files

Secure Boot can be configured to also trust user keys. Ubuntu's installer does it automatically if you choose to install it with third-party drivers (like Nvidia). Those user keys are then available to root to sign any DKMS kernel modules.
Take that, memory-safe programming languages!
Drawing to the vga frame buffer back in dos used to be as simple as setting a pointer to 0xA0000 in your c(++) program and writing to it. Fond memories!