Linux raw input without root permission? - linux

On a linux program, on the console (as in no xorg, etc), I'm using using /dev/input/event* to read keyboards and mice, however I need to be root to be able to read them. Is there an alternative form to read that stuff without needing root privileges (without having to change permisons and config files, etc)?
I understand why it does that by default no need to explain that.

yes, it's possible by creating a udev rule, see this HowTo
For example as root, create the file /etc/udev/rules.d/99-input.rules:
KERNEL=="event*", NAME="input/%k", MODE="660", GROUP="input"
Note: you will probably need to create the group "input" first.

Check to see to which group the device files belong to. For example, here I get:
$ ls -l /dev/input/
...
crw-rw---- 1 root plugdev 13, 64 Nov 4 18:01 event0
crw-rw---- 1 root plugdev 13, 65 Nov 4 18:01 event1
crw-rw---- 1 root plugdev 13, 66 Nov 4 18:01 event2
crw-rw---- 1 root plugdev 13, 67 Nov 4 18:01 event3
crw-rw---- 1 root plugdev 13, 68 Nov 4 18:01 event4
...
The user executing your program needs to be in the plugdev group on this system. Something similar is probably the case on your system.
If you're asking for a way to circumvent that (reading or writing to the device without being in the group), then no. That would obviously defeat the purpose of security though user groups.
An alternative to reading the event devices directly would be to use an appropriate user space API instead. For example, to read the keyboard you would use ncurses, and to read the mouse you would use GPM.

Related

what happens if I create a file using vim in /dev directory. How the file will be created as the /dev is not standard file system

What happens if I create a file using vim in the /dev directory. How will the file be created as the /dev is not a standard file system. I can see a file being created but standard Kernel file operation create was not called. Now I am not sure how this file was created by kernel. Will it use some udev bound Kernel API to create this file.
Note : I can see the file in /dev after creation. Look at the ls output below.
crw-rw-rw- 1 root tty 5, 0 Aug 24 17:32 tty
-rw-r--r-- 1 root root 35 Aug 24 17:37 abc
-rw-r--r-- 1 root root 0 Aug 24 17:37 ght
-rw-r--r-- 1 root root 0 Aug 24 17:51 ioiu
I want to find this out to determine what will happen if some illegal SW forcefully writes to /dev directory , how can I find that out.
If you try in MacOS it won't work even as root.
If you try in CentOS 8 it will work if you're root.
Other Linux flavors your mileage may vary.
It is a very interesting directory that highlights one important aspect of the Linux filesystem - everything is a file or a directory.
Example
[root]# date > /dev/date
[root]# cat /dev/date
Tue Aug 24 19:13:04 UTC 2021
All that being said, your concern about nefarious software creating a file in this specific directory seems too specific. If the software has the ability to write to /dev it can write to anywhere and hide in plain site. If you're really concerned about this, install a file integrity monitoring (FIM) package to monitor file CRUD.
References
dev filesystem

Programmatically create a btrfs file system whose root directory has a specific owner

Background
I have a test script that creates and destroys file systems on the fly, used in a suite of performance tests.
To avoid running the script as root, I have a disk device /dev/testdisk that is owned by a specific user testuser, along with a suitable entry in /etc/fstab:
$ ls -l /dev/testdisk
crw-rw---- 1 testuser testuser 21, 1 Jun 25 12:34 /dev/testdisk
$ grep testdisk /etc/fstab
/dev/testdisk /mnt/testdisk auto noauto,user,rw 0 0
This allows the disk to be mounted and unmounted by a normal user.
Question
I'd like my script (which runs as testuser) to programmatically create a btrfs file system on /dev/testdisk such that the root directory is owned by testuser:
$ mount /dev/testdisk /mnt/testdisk
$ ls -la /mnt/testdisk
total 24
drwxr-xr-x 3 testuser testuser 4096 Jun 25 15:15 .
drwxr-xr-x 3 root root 4096 Jun 23 17:41 ..
drwx------ 2 root root 16384 Jun 25 15:15 lost+found
Can this be done without running the script as root, and without resorting to privilege escalation (use of sudo) within the script?
Comparison to other file systems
With ext{2,3,4} it's possible to create a filesystem whose root directory is owned by the current user, with the following command:
mkfs.ext{2,3,4} -F -E root_owner /dev/testdisk
Workarounds I'd like to avoid (if possible)
I'm aware that I can use the btrfs-convert tool to convert an existing (possibly empty) ext{2,3,4} file system to btrfs format. I could use this workaround in my script (by first creating an ext4 filesystem and then immediately converting it to brtfs) but I'd rather avoid it if there's a way to create the btrfs file system directly.

Some high level questions about how PAM is designed

I'm creating a PAM module for a project. The PAM module will be using a library that will be re-used by some command line utilities (rather than re-writing everything each time). In this library, I want to have it interpret policy that discriminate against and/or logs according to subnet memberships of the remote host. Near as I can tell this value is probably coming from the authenticating application, but I don't know. Since the shared object won't have access to the pamh structure from libpam I can't just do a pam_get_item (like I would be able to from the PAM module itself) so I've had to resort to other means.
The best solution I've come up with is to have the shared object look for a connected TTY, if it's there go to utmp and find the login process associated with that TTY, extract the IP address from there. If there isn't a TTY, assume it's an initial login of a network user. The library then iterates over the sockets (which I've defined as basically any symlink with the word "socket" in the target's filename when you do a ls -l /proc/<pid>/fd) and uses the socket inode number to cross reference with /proc/net/tcp and extracts the remote IP address associated with that inode number. If it doesn't find an inode there then it assumes it's Unix domain or tcp6 (IPv6 support in this is forthcoming and not terribly important for the near future). If it still isn't able to find it, assume that some daemon has called an application linking against it and interpret it as such (might do something eventually, if it's worthwhile, but for now it's just a big NOOP if the first two don't return anything.
It seems to work but I have some high level questions about how PAM is supposed to work:
Is there some official standard that governs PAM operation? For example, is it covered by a POSIX standard somewhere? I know there are multiple PAM implementations (four or five that I've found thusfar) but I don't know if existing commonalities are de jure or de facto or just how I happen to have my system configured.
After I did a ls -l /proc/<pid>/fd > /lsOutput from the module itself (via system()):
[root#hypervisor pam]# cat /lsOutput total 0
lrwx------. 1 root root 64 Jun 15 15:09 0 -> /dev/null
lrwx------. 1 root root 64 Jun 15 15:09 1 -> /dev/null
lrwx------. 1 root root 64 Jun 15 15:09 2 -> /dev/null
lr-x------. 1 root root 64 Jun 15 15:09 3 -> socket:[426180]
[root#hypervisor pam]#
And issuing a manual ls after the user logins in:
[root#hypervisor pam]# ls -l /proc/18261/fd
total 0
lrwx------. 1 root root 64 Jun 15 15:15 0 -> /dev/null
lrwx------. 1 root root 64 Jun 15 15:15 1 -> /dev/null
lrwx------. 1 root root 64 Jun 15 15:15 11 -> /dev/ptmx
lrwx------. 1 root root 64 Jun 15 15:15 12 -> /dev/ptmx
lrwx------. 1 root root 64 Jun 15 15:15 13 -> socket:[426780]
lrwx------. 1 root root 64 Jun 15 15:15 14 -> socket:[426829]
lrwx------. 1 root root 64 Jun 15 15:15 2 -> /dev/null
lrwx------. 1 root root 64 Jun 15 15:15 3 -> socket:[426180]
lrwx------. 1 root root 64 Jun 15 15:15 4 -> socket:[426322]
lr-x------. 1 root root 64 Jun 15 15:15 5 -> pipe:[426336]
l-wx------. 1 root root 64 Jun 15 15:15 6 -> pipe:[426336]
lrwx------. 1 root root 64 Jun 15 15:15 7 -> socket:[426348]
lrwx------. 1 root root 64 Jun 15 15:15 8 -> socket:[426349]
lrwx------. 1 root root 64 Jun 15 15:15 9 -> /dev/ptmx
[root#hypervisor pam]#
So basically, it seems like both the TTY and any additional sockets get opened only AFTER the session modules finish (my temporary test module's session handling is the last in the stack for the sshd service). I've been unable to get it to be otherwise (or even think of a time when the connecting client won't be a TCP socket at descriptor 3).
Is this just due to my lack of imagination or is it necessarily so? I'm leaning towards the latter as it would seem that communicating with the client would be a pre-requisite to doing pretty much anything else that's useful. I don't know that for sure, so I feel I should ask somebody. Will descriptor 3 always be the authenticating client (my .so only makes the assumption that it's the lowest numbered TCP socket, and only if there's no TTY, but it seems like 3 should always be the descriptor for the connecting client). Would pulling the first TCP descriptor be a "deterministic" way of establishing the remote client's identity? Or is there no prescribed way this is supposed to play out and that's just how either my system is configured or how SSH has chosen to interface with PAM?
Is it sshd that's setting the rhost value or is that coming from some place else? I've tried grep-ing over the source code for both SSH and libpam, but no dice. I can see where libpam handles the setting of the host value when something call pam_set_item, but not were pam_set_item actually gets called to set it to be this or that particular host.
Any amount of help would be appreciated, I've googled but I'm starting to get splinters on my fingertips from scraping the bottom of the barrel.
Main reason I'm interested in knowing this is so that I'll end up not only with the "right" answer but mostly so that I won't have any surprises later on down the road. We have some Solaris platforms we may do this on, but my main motivation is to have assumptions that are grounded in things that are actually going to be constant.
I also realize that I could have the client programs/modules feed the host information to the library, but that would likely involve code re-write two or three times (as the CLI tools prepare session information from utmp and the PAM module from pam_get_item) and potentially make the project look more complex than it really needs to be.
Answering some of your questions:
"Is there some official standard that governs PAM operation?"
Apparently, yes. Wikipedia's entry on Pluggable_Authentication_Modulesays "PAM was standardized as part of the X/Open UNIX standardization process, resulting in the X/Open Single Sign-on (XSSO) standard." I have never found this particularly relevant to my dealings with it.
"Is this just due to my lack of imagination or is it necessarily so?"
<magicEightBall>"Concentrate and ask again"</magicEightBall> (It's ambiguous which "this" is being referred to - perhaps you can clarify?
"Will descriptor 3 always be the authenticating client?"
This is a behaviour of the application, rather than PAM.
Would pulling the first TCP descriptor be a "deterministic" way of establishing the remote client's identity?
Also a behaviour of the application.
"Is it sshd that's setting the rhost value or is that coming from some place else?"
It is sshd that sets the rhost value. In openssh's file auth-pam.c, function sshpam_init(), you'll find:
sshpam_err = pam_set_item(sshpam_handle, PAM_RHOST, pam_rhost);
Some general notes:
rather than keying off the TTY - which, as you've discovered get set later - you can walk the process lineage via getppid() and /proc.
don't trust system() in PAM modules - it uses a user's environment, and may not be the one you expect. Use fork()/execlp() instead.

How to start init.d script on bootup in embedded linux. I dont have update-rc.d. Is there any other way to start init.d script on linux boot?

I am have a Linux board on which I have added one init script under /etc/init.d/ directory. I can start,stop,restart service using script manually. For Debian we do use "update-rc.d" to execute this script at boot time. But i don't have this command, How then can i execute the script at boot time? Is there any alternate way to do this?
You can edit the /etc/inittab file.
Also, there are 2 other alternatives to update-rc.d:
Rcconf - Rcconf allows you to control which services are started when the system boots up or reboots. It displays a menu of all the
services which could be started at boot. The ones that are configured
to do so are marked and you can toggle individual services on and
off.This tool configures system services in connection with system
runlevels. It turns on/off services using the scripts in /etc/init.d/.
File-rc - Alternative boot mechanism using a single configuration file This package provides an alternative mechanism to boot the
system, to shut it down and to change runlevels. The /etc/rc?.d/*
links will be converted into one single configuration file
/etc/runlevel.conf instead, which is easier to administrate than
symlinks, and is also more flexible. The package will automatically
convert your existing symlinks into the file method on installation,
and convert the file back into symlinks on removal.
inittab has some other uses. The main use is creating "unkillable" service, that will be restarted every time it dies.
If you need just usual service, you can just create symlinks manually. Example from apache, like very typical service with default runlevels.
# ls -la /etc/rc*.d/*apache2
lrwxrwxrwx 1 root root 17 Oct 2 13:45 /etc/rc0.d/K02apache2 -> ../init.d/apache2
lrwxrwxrwx 1 root root 17 Oct 2 13:45 /etc/rc1.d/K02apache2 -> ../init.d/apache2
lrwxrwxrwx 1 root root 17 Oct 2 13:45 /etc/rc2.d/S02apache2 -> ../init.d/apache2
lrwxrwxrwx 1 root root 17 Oct 2 13:45 /etc/rc3.d/S02apache2 -> ../init.d/apache2
lrwxrwxrwx 1 root root 17 Oct 2 13:45 /etc/rc4.d/S02apache2 -> ../init.d/apache2
lrwxrwxrwx 1 root root 17 Oct 2 13:45 /etc/rc5.d/S02apache2 -> ../init.d/apache2
lrwxrwxrwx 1 root root 17 Oct 2 13:45 /etc/rc6.d/K02apache2 -> ../init.d/apache2
So it should be killed at runlevels 0 1 6 and started on runlevels 2 3 4 5.

how does a process in linux decides privileges it has

I want to know how does a process in Linux decides what privileges it has?
Suppose there is a binary program Read_File that reads from file /home/myname/data.txt and displays the contents of it to the STD output; now, how does Read_File decides whether or not it has permission to read data.txt, what type of ids it checks to decide the privileges?
First, a bit of background:
The process is usually run by a specific user. So for example, if you log in yourself and run the program, it will run with the same privileges as yourself. You can check the permissions on the file with either stat or ls -l.
Using stat
malbert#dredg:/tmp$ stat foo
File: `foo'
Size: 0 Blocks: 0 IO Block: 4096 regular empty file
Device: fb00h/64256d Inode: 618 Links: 1
Access: (0644/-rw-r--r--) Uid: (11204/ malbert) Gid: (10513/domain users)
Access: 2011-06-10 13:03:27.181227226 +0200
Modify: 2011-06-10 13:03:27.181227226 +0200
Change: 2011-06-10 13:03:27.181227226 +0200
The important infos here are:
Access: (0644/-rw-r--r--) Uid: (11204/ malbert) Gid: (10513/domain users)
This tells you the permissions for the owner (rw-), group (r--) and everyone else (r--). It also shows you the current owner id (Uid) and the current group id (Gid).
The abbreviations stand for:
r = read access
w = write access
x = execute/traverse directory access
Using ls -l
ls -l gives you a quick summary:
malbert#dredg:/tmp$ ls -l /tmp
total 48
drwx------ 2 malbert domain users 4096 2011-06-10 08:51 akonadi-malbert.zOSngu
-rw-r--r-- 1 malbert domain users 0 2011-06-10 13:03 foo
drwx------ 2 kdm nogroup 4096 2011-06-10 08:51 kde-kdm
drwx------ 3 malbert domain users 4096 2011-06-10 08:51 kde-malbert
[snip]
Here you can see the same info as with stat, but as a summary. Also, the uid's and gid's are resolved into names (in this case malbert and domain users). You can use ls -u to see these as numeric values.
In case you want to run the application as a different user as yourself, you can either use su, sudo or your application itself can drop priviledges and change the user it is running as. This is usually the way system daemons do things.
ACLs / extended attributes
Be careful about extended attributes. When listing the files using ls -l these are visible with an appended + sign. For example:
malbert#dredg:/tmp$ ls -l
total 48
drwx------ 2 malbert domain users 4096 2011-06-10 08:51 akonadi-malbert.zOSngu
-rw-rwxr--+ 1 malbert domain users 0 2011-06-10 13:03 foo
drwx------ 2 kdm nogroup 4096 2011-06-10 08:51 kde-kdm
drwx------ 3 malbert domain users 4096 2011-06-10 08:51 kde-malbert
[snip]
Notice the following line:
-rwxr--+ 1 malbert domain users 0 2011-06-10 13:03 foo
The + sign in -rwxr--+ points to extended attributes. It is possible that these are ACLs. There is an excellent document on ACLs in the SuSE documentation. Go have a look at it if you need to. Explaining ACLs would certainly explode this article, so I won't discuss those.
Extended attributes could also be related to the file system. See the man page of chattr for more information on that.
Now, as a sidenote: this is StackOverflow. Questions should be development related. For questions like this one, there's http://www.serverfault.com. But As you were not aware, that this is not a development problem, but more related to the OS, I felt I should answer anyway ;)
Good luck, and have fun!
The process doesn't decide anything; whenever it tries an operation the operating system checks it's EUID and decides if has the required privileges.
For example when it tries to access a file, the owner and permissions of the file are checked. If the EUID of the process doesn't have enough privileges for an operation, that operation will fail (usually with EPERM).

Resources