Does inotify work in the face of poorly synchronized clocks? - linux

Here's the scenario:
A central machine running Linux is a "data store" for a number of instruments.
The instruments each have a PC, and each one has a remote mount (SMB) on the data store to which it write data files captured by the instrument.
The instrument PCs run a wide range of operating system including some really old ones.
The instrument PCs hardware clocks are not synchronized, and synchronizing would be problematic for a number of reasons.
Various other fixes (e.g. not using SMB, upgrading instrument operating systems, developing stuff to run on the instruments) are likewise problematic.
What we want to write is a "grabber" application that notices when an instrument writes a file to the data store via its remote mount, and then quickly copies the file somewhere else. The current plan is to use the Linux inotify subsystem to watch for file system events on the directories / trees that the files are likely to arrive in, and then do the copying.
My concern is that the fact the fact that we don't have synchronized clocks is going to be a problem. Is this concern justified?

The concern is not justified.
Linux inotify is an user space API that exposes the Linux fsnotify sub-system. This kernel file system is wired into the general file system layer of the kernel (called VFS). It gets the notification of a creation of a new file directly from the file system code by a callback function, and not by comparing the creation or access dates of the files in a directory. As such, it will not be influenced at all by the time stamps on the files, so the clocks on the different client machine would not matter at all.
To be sure you audit the code for the inotify_should_send_event() send event function, that checks whether an event needs to sent for a tracked file or directory (see here: http://lxr.linux.no/linux+v3.0.4/fs/notify/inotify/inotify_fsnotify.c#L144). Note there is no reference whatsoever to time. In the same spirit the main fsnotify function (http://lxr.linux.no/linux+v3.0.4/fs/notify/fsnotify.c#L296) in the kernel does not reference time stamps anywhere, so clocks will not affect this interface at all.
I hope this helps.

Related

PyQt5 segmentation fault when trying to save file to disk in real-time app

I had a completely working, fully-debugged PyQt5 application which 1) accepted streaming real-time data from a USB peripheral, 2) allowed data recording and 3) saved recorded data to disk. I'm running on top of Ubuntu Linux 17.10.
This application is now broken. The Linux operating system is not connecting to the USB peripheral dependably. Kernel updates may be involved. The problem is complicated, and I discuss it here if you are interested in the details. I'm trying to fix this problem. In the mean time, I need to collect data from the device.
My original application allowed full-duplex communications over the USB. So in the original application, when I wanted to open a QFileDialog to save data to disk, I first issued a command to instruct the peripheral to stop transmitting. It has been a long time since I wrote this program and I don't remember whether this was truly necessary to avoid a crash, it just seemed like a smart thing to do.
When the OS fails to cooperate, I can no longer do this. I only have half-duplex communication. The peripheral must start automatically and must keep running.
My program works as before, right up to the point where I save data. I open the QFileDialog, I name the file and save it. The file actually does save to disk, but after that the segmentation fault occurs.
I am trying to devise a work-around for this situation. Any suggestions are appreciated! Thanks.

OS - How does OS map ready device data to respective processes

Let's take a hard drive/network interface. It is shared by multiple processes. Now multiple processes may issue concurrent commands to the hard drive to read data. When the data is available, how does the kernel know for which process has the data become ready? Is there some protocol followed between the OS and the hard drive. i.e. some metadata that is returned with the ready data?
When it comes to data specific to each process (e.g. accessing file opened from filesystem on harddrive or receiving network) it is usually serialized using locking mechanisms. The "protocol" (assigning proper retrieved data to requesting process) is afaik more or less driver or kernel part specific - done differently in e.g. networking code and virtual file system code.
This is very well described in chapter called "Concurrency and Race Conditions" of Linux Device Drivers book by Kroah-Hartman, Rubini, Corbet. You can take a look here: https://www.safaribooksonline.com/library/view/linux-device-drivers/0596005903/ch05.html

Is it possible to circumvent OS security by not using the supplied System Calls?

I understand that an Operating System forces security policies on users when they use the system and filesystem via the System Calls supplied by stated OS.
Is it possible to circumvent this security by implementing your own hardware instructions instead of making use of the supplied System Call Interface of the OS? Even writing a single bit to a file where you normally have no access to would be enough.
First, for simplicity, I'm considering the OS and Kernel are the same thing.
A CPU can be in different modes when executing code.
Lets say a hypothetical CPU has just two modes of execution (Supervisor and User)
When in Supervisor mode, you are allowed to execute any instructions, and you have full access to the hardware resources.
When in User mode, there is subset of instructions you don't have access to, such has instructions to deal with hardware or change the CPU mode. Trying to execute one of those instructions will cause the OS to be notified your application is misbehaving, and it will be terminated. This notification is done through interrupts. Also, when in User mode, you will only have access to a portion of the memory, so your application can't even touch memory it is not supposed to.
Now, the trick for this to work is that while in Supervisor Mode, you can switch to User Mode, since it's a less privileged mode, but while in User Mode, you can't go back to Supervisor Mode, since the instructions for that are not permitted anymore.
The only way to go back to Supervisor mode is through system calls, or interrupts. That enables the OS to have full control of the hardware.
A possible example how everything fits together for this hypothetical CPU:
The CPU boots in Supervisor mode
Since the CPU starts in Supervisor Mode, the first thing to run has access to the full system. This is the OS.
The OS setups the hardware anyway it wants, memory protections, etc.
The OS launches any application you want after configuring permissions for that application. Launching the application switches to User Mode.
The application is running, and only has access to the resources the OS allowed when launching it. Any access to hardware resources need to go through System Calls.
I've only explained the flow for a single application.
As a bonus to help you understand how this fits together with several applications running, a simplified view of how preemptive multitasking works:
In a real-world situation. The OS will setup an hardware timer before launching any applications.
When this timer expires, it causes the CPU to interrupt whatever it was doing (e.g: Running an application), switch to Supervisor Mode and execute code at a predetermined location, which belongs to the OS and applications don't have access to.
Since we're back into Supervisor Mode and running OS code, the OS now picks the next application to run, setups any required permissions, switches to User Mode and resumes that application.
This timer interrupts are how you get the illusion of multitasking. The OS keeps changing between applications quickly.
The bottom line here is that unless there are bugs in the OS (or the hardware design), the only way an application can go from User Mode to Supervisor Mode is through the OS itself with a System Call.
This is the mechanism I use in my hobby project (a virtual computer) https://github.com/ruifig/G4DevKit.
HW devices are connected to CPU trough bus, and CPU does use to communicate with them in/out instructions to read/write values at I/O ports (not used with current HW too much, in early age of home computers this was the common way), or a part of device memory is "mapped" into CPU address space, and CPU controls the device by writing values at defined locations in that shared memory.
All of this should be not accessible at "user level" context, where common applications are executed by OS (so application trying to write to that shared device memory would crash on illegal memory access, actually that piece of memory is usually not even mapped into user space, ie. not existing from user application point of view). Direct in/out instructions are blocked too at CPU level.
The device is controlled by the driver code, which is either run is specially configured user-level context, which has the particular ports and memory mapped (micro-kernel model, where drivers are not part of kernel, like OS MINIX). This architecture is more robust (crash in driver can't take down kernel, kernel can isolate problematic driver and restart it, or just kill it completely), but the context switches between kernel and user level are a very costly operation, so the throughput of data is hurt a bit.
Or the device drivers code runs on kernel-level (monolithic kernel model like Linux), so any vulnerability in driver code can attack the kernel directly (still not trivial, but lot more easier than trying to get tunnel out of user context trough some kernel bug). But the overall performance of I/O is better (especially with devices like graphics cards or RAID disc clusters, where the data bandwidth goes into GiBs per second). For example this is the reason why early USB drivers are such huge security risk, as they tend to be bugged a lot, so a specially crafted USB device can execute some rogue code from device in kernel-level context.
So, as Hyd already answered, under ordinary circumstances, when everything works as it should, user-level application should be not able to emit single bit outside of it's user sandbox, and suspicious behaviour outside of system calls will be either ignored, or crash the app.
If you find a way to break this rule, it's security vulnerability and those get usually patched ASAP, when the OS vendor gets notified about it.
Although some of the current problems are difficult to patch. For example "row hammering" of current DRAM chips can't be fixed at SW (OS) or CPU (configuration/firmware flash) level at all! Most of the current PC HW is vulnerable to this kind of attack.
Or in mobile world the devices are using the radiochips which are based on legacy designs, with closed source firmware developed years ago, so if you have enough resources to pay for a research on these, it's very likely you would be able to seize any particular device by fake BTS station sending malicious radio signal to the target device.
Etc... it's constant war between vendors with security researchers to patch all vulnerabilities, and hackers to find ideally zero day exploit, or at least picking up users who don't patch their devices/SW fast enough with known bugs.
Not normally. If it is possible it is because of an operating system software error. If the software error is discovered it is fixed fast as it is considered to be a software vulnerability, which equals bad news.
"System" calls execute at a higher processor level than the application: generally kernel mode (but system systems have multiple system level modes).
What you see as a "system" call is actually just a wrapper that sets up registers then triggers a Change Mode Exception of some kind (the method is system specific). The system exception hander dispatches to the appropriate system server.
You cannot just write your own function and do bad things. True, sometimes people find bugs that allow circumventing the system protections. As a general principle, you cannot access devices unless you do it through the system services.

What's the difference between a VFS and an NFS?

This might be a dumb question, but I'm struggling to find resources that clearly explain how a VFS is different from an NFS. Can they both be used for the same purpose?
Bonus question: Can you watch a VFS with inotify like you can an NFS?
"NFS" is a network filesystem that's been around for decades. Wikipedia has you covered on that front.
"VFS" is a more generic term that simply means "virtual filesystem". Within the context of Linux, it refers to the part of the kernel with which your user-space programs actually interact when they interact with "files". The VFS layer then passes requests to a concrete filesystem driver -- such as NFS, for example, or ext4, or others.
Read more here and here.
A virtual file system (VFS) is an abstraction layer on top of a more concrete file system.The purpose of a VFS is to allow client applications to access different types of concrete file systems in a uniform way, Where as Network File System (NFS) is a distributed file system protocol originally developed by Sun Microsystem in 1984, allowing a user on a client computer to access files over a computer network much more like local storage is accessed
A VFS can be used to access local and network storage devices transparently without the client application noticing the difference. It can be used to bridge the differences in Windows, Mac and Unix file systems, so that applications can access files on local file systems of those types without having to know what type of file system they are accessing Where as, NFS like many other protocols, builds on the Open Newtork Computing Remote Procedure Call (ONC RPC) system. The NFS is an open standard defined in Request for comments (RFC), allowing anyone to implement the protocol.
"VFS" is the name given to the entire layer in the kernel situated between the system calls and the filesystem drivers; it is not a filesystem in its own right.

What Really Protects File Priveleges?

In Windows for instance, and all operating systems, file priveleges exist that "prevent" a file from being written to if that rule is set.
This is hard to describe but please listen. People coding in a C language obviously would use some form of framework to easily modify a file. Using the built-in .Net framework, Microsoft obviously would put prevention into their classes checking file permissions before writing to a file. Since file permissions are stored via software and not hardware, what really prevents a file from being tampered with?
Let's hop over to Assembly. Suppose I create an Assembly program that directly accesses hard drive data and changes the bytes of a file. How could file permissions possibly prevent me from doing this? I guess what I am trying to ask is how a file permission really stays secure if the compiled program does not check for file permissions before writing to a file?
Suppose I create an Assembly program that directly accesses hard drive data and changes the bytes of a file. How could file permissions possibly prevent me from doing this?
If you write in assembly, your assembly is still run in a CPU mode that prevents direct access to memory and devices.
CPU modes … place restrictions on the type and scope of operations that can be performed by certain processes being run by the CPU. This design allows the operating system to run with more privileges than application software.
Your code still needs to issue system calls to get the OS to interact with memory not owned by your process and devices.
a system call is how a program requests a service from an operating system's kernel. This may include hardware related services (e.g. accessing the hard disk), creating and executing new processes, and communicating with integral kernel services (like scheduling).
The OS maintains security by monopolizing the ability to switch CPU modes and by crafting system calls so that they are safe for user-land code to initiate.

Resources