Impossible to delete file in debugfs - linux

I'm playing with debugfs. In a module, I've created a directory 'test_debugfs' in the debugfs filesystem (mounted at /sys/kernel/debug) and a file 'demo_file'.
// Create the test_debufs in /sys/kernel/debug
struct dentry * my_dirent;
static int __init my_module_init_module(void) {
my_dirent = debugfs_create_dir("test_debugfs", NULL);
debugfs_create_file("demo_file", 0666, my_dirent, NULL, &fops_debugfs);
}
Unfortunately, I forgot to remove the directory on module unload, and now I cannot remove the demo_file anymore.
# rmmod my_module
# cd /sys/kernel/debug/test_debugfs
# ls
demo_file
# rm -rf demo_file
rm: cannot remove 'demo_file': Operation not permitted
# sstat
File: demo_file
Size: 0 Blocks: 0 IO Block: 4096 regular empty file
Device: 6h/6d Inode: 16426 Links: 1
Access: (0666/-rw-rw-rw-) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2021-04-28 10:20:14.807999989 +0200
Modify: 2021-04-28 10:20:14.807999989 +0200
Change: 2021-04-28 10:20:14.807999989 +0200
Birth: -
After rebooting my machine, the demo_file is still there.
Do you know how I could remove it ?
Answer:
Thanks to Varun, I managed to remove the file directly in the module with this code:
struct dentry * my_dirent;
static int __init my_module_init_module(void) {
struct path path;
ret = kern_path("/sys/kernel/debug/test_debugfs", LOOKUP_DIRECTORY, &path);
if (ret)
pr_err("Failed to lookup /sys/kernel/debug/test_debugfs err %d\n", ret);
else
debugfs_remove_recursive(path.dentry);
}

You cannot use rm command to remove file from debug_fs ..
The debugfs filesystem does not support unlink function in the directory inode operations. Hence rm command will fail
You have to use debugfs function void debugfs_remove(struct dentry *dentry) where dentry parameter is the return value from debugfs_create_file function call

Related

Write to a sysfs node, causing the system always write to the node

I locally wirte a module to test function/feature, And I create follow node info:
/sys/class/dbc/dbc # ls -l
total 0
-rw------- 1 root root 4096 2021-10-08 21:52 dbc_backlight
-rw------- 1 root root 4096 2021-10-08 22:30 dbc_pwm_max
-rw------- 1 root root 4096 2021-10-08 22:30 dbc_pwm_min
-rw------- 1 root root 4096 2021-10-08 21:52 dbc_setting
-rw------- 1 root root 4096 2021-10-08 21:52 dbc_thread_enable
-r--r--r-- 1 root root 4096 2021-10-08 22:30 dev
drwxr-xr-x 2 root root 0 2021-10-08 22:30 power
lrwxrwxrwx 1 root root 0 2021-10-08 22:30 subsystem -> ../../../../class/dbc
-rw-r--r-- 1 root root 4096 2021-10-08 22:30 uevent
when I echo right value to dbc_backlight node, can normally work, but when I write error value to dbc_backlight node, will result always write, info is follow:
node source code is follow:
static ssize_t dbc_backlight_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
unsigned int DBC_BACKLIGHT = 0;
int readCount = 0;
printk("===========Set DBC Backlight========\n");
readCount = sscanf(buf, "%d", &DBC_BACKLIGHT);
if (readCount != 1)
{
printk("[ERROR] cannot read DBC_BACKLIGHT from [%s] \n", buf);
return 0;
}
if (DBC_BACKLIGHT > 100)
{
printk("Invalid Parameter DBC_BACKLIGHT=%d \n", DBC_BACKLIGHT);
return 0;
}
printk("Set Parameter DBC_BACKLIGHT=%d success\n", DBC_BACKLIGHT);
m_u8BacklightSetting = DBC_BACKLIGHT;
SetActiveBacklightSwitch(m_eActiveBackLight, m_u8BacklightSetting);
return count;
}
abnormal status dmesg log info is:
[ 2562.416693] ===========Set DBC Backlight========
[ 2562.416739] Invalid Parameter DBC_BACKLIGHT=101
[ 2562.416786] ===========Set DBC Backlight========
[ 2562.416832] Invalid Parameter DBC_BACKLIGHT=101
[ 2562.416878] ===========Set DBC Backlight========
[ 2562.416960] Invalid Parameter DBC_BACKLIGHT=101
[ 2562.417006] ===========Set DBC Backlight========
[ 2562.417089] Invalid Parameter DBC_BACKLIGHT=101
[ 2562.417135] ===========Set DBC Backlight========
[ 2562.417181] Invalid Parameter DBC_BACKLIGHT=101
[ 2562.417265] ===========Set DBC Backlight========
[ 2562.417309] Invalid Parameter DBC_BACKLIGHT=101
[ 2562.417391] ===========Set DBC Backlight========
[ 2562.417436] Invalid Parameter DBC_BACKLIGHT=101
[ 2562.417481] ===========Set DBC Backlight========
[ 2562.417564] Invalid Parameter DBC_BACKLIGHT=101
the log will always running and can't stop, otherwise, kill -9 pid can kill(kill pid can't kill it), top info is follow:
Tasks: 410 total, 2 running, 349 sleeping, 0 stopped, 0 zombie
Mem: 1694992k total, 1583088k used, 111904k free, 12844k buffers
Swap: 409596k total, 13056k used, 396540k free, 732388k cached
400%cpu 6%user 102%nice 135%sys 157%idle 0%iow 0%irq 0%sirq 0%host
PID USER PR NI VIRT RES SHR S[%CPU] %MEM TIME+ ARGS
2272 logd 30 10 34M 9.4M 4.1M S 152 0.5 2:29.57 logd
10181 root 20 0 4.4M 2.3M 1.9M R 98.6 0.1 1:33.14 sh -
kill -9 10181 can stop thread running.
I don't know why always write the node(dbc_backlight), please help me.
And locally, I do follow modify, the problem will not reproduce:
printk("===========Set DBC Backlight========\n");
readCount = sscanf(buf, "%d", &DBC_BACKLIGHT);
if (readCount != 1)
{
printk("[ERROR] cannot read DBC_BACKLIGHT from [%s] \n", buf);
return 0;
}
if (DBC_BACKLIGHT > 100)
{
printk("Invalid Parameter DBC_BACKLIGHT=%d \n", DBC_BACKLIGHT);
return 0;
}
//modify follow will fix it the problem
printk("===========Set DBC Backlight========\n");
readCount = sscanf(buf, "%d", &DBC_BACKLIGHT);
if (readCount != 1)
{
printk("[ERROR] cannot read DBC_BACKLIGHT from [%s] \n", buf);
return -EINVAL; //........
}
if (DBC_BACKLIGHT > 100)
{
printk("Invalid Parameter DBC_BACKLIGHT=%d \n", DBC_BACKLIGHT);
return -EINVAL;........
}
Do you know why? thanks for your help.
On success, .store function should return number of characters written.
In fail, it should return negative error code.
Returning 0 (return 0;) from that function is incorrect.
As you correctly noted, you can use return -EINVAL; for indicate that input is invalid.

No permissions to change tty mode inside a docker container

I'm trying to run some software inside a docker container, which wants to do VT_SETMODE for the tty currently in use. This will always fail with an error saying "Operation not permitted".
I've tried playing around with permissions/groups with no luck.
Finally I created a small snippet to reproduce the error:
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <linux/vt.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
int main() {
const char *tty_path;
tty_path = "/dev/tty1";
int fd = open(tty_path, O_RDWR | O_CLOEXEC);
if (fd < 0) {
printf("ERROR: Failed to open %s\n", strerror(errno));
return 1;
}
struct vt_mode mode = {
.mode = VT_AUTO,
};
errno = 0;
ioctl(fd, VT_SETMODE, &mode);
if (errno) {
printf("ERROR: %s\n", strerror(errno));
return 1;
}
return 0;
}
I ran the code inside a docker container with a simple dockerfile:
FROM archlinux/base
RUN pacman -Sy --noconfirm gcc
That was started with command:
docker build -f Dockerfile -t tty-test . && docker run --device /dev/tty1 -v $HOME/tty-test:/volume -it tty-test /bin/bash -c 'cd /volume && gcc tty_r.c && ./a.out ; /bin/bash'
Output is this:
ERROR: Operation not permitted
Can anyone explain why the tty is not accessible from the container, or is there some way to give more control to the container?
Okay it seems that I have solved my own problem. I was trying to run the code inside a container which had no privilege to do tty-configuration. Adding --cap-add SYS_TTY_CONFIG to the docker run command fixed the issue.

How to determine if an SFTP file is a directory in Node.js?

The ssh2 library's SFTP readdir method gives me back all the files in the remote directory. How can I tell if any of of them are directories?
Here's some example output from the library:
{ filename:
'myfile',
longname:
'-rwxr-x--- 1 myuser mygroup 19036227 Nov 21 11:05 myfile',
attrs:
Stats {
mode: 33256,
permissions: 33256,
uid: 603,
gid: 1014,
size: 19036227,
atime: 1542859216,
mtime: 1542816340 } }
The file's mode contains bits indicating its type. You can check it like this:
const fs = require('fs');
function isDir(mode) {
return (mode & fs.constants.S_IFMT) == fs.constants.S_IFDIR;
}
isDir(myfile.attrs.mode);

puppet not working with keys() and hiera_hash()

I have in hiera node variable solr_enabled = true. Also I have in this node list of fstab mount points like:
fstab_homes:
'/home1':
device: 'UUID=ac2ca97e-8bce-4774-92d7-051482253089'
'/home2':
device: 'UUID=d9daaeed-4e4e-40e9-aa6b-73632795e661'
'/home3':
device: 'UUID=21a358cf-2579-48cb-b89d-4ff43e4dd104'
'/home4':
device: 'UUID=c68041de-542a-4f72-9488-337048c41947'
'/home16':
device: 'UUID=d55eff53-3087-449b-9667-aeff49c556e7'
In solr.pp I want to get the first mounted home disk, create there folder and make symbolic link to /home/cpanelsolr.
For this I wrote the code /etc/puppet/environments/testing/modules/cpanel/manifests/solr.pp:
# Install SOLR - dovecot full text search plugin
class cpanel::solr(
$solr_enable = hiera('solr_enabled',false),
$homes = hiera_hash('fstab_homes', false),
$homesKeys = keys($homes),
)
{
if $solr_enable == true {
notify{"Starting Solr Installation ${homesKeys[0]}":}
if $homes != false and $homesKeys[0] != '/home' {
file { "Create Solr home symlink to ${homesKeys[0]}":
path => '/home/cpanelsolr',
ensure => 'link',
target => "${homesKeys[0]}/cpanelsolr",
}
}
exec { 'cpanel-dovecot-solr':
command => "/bin/bash -c
'/usr/local/cpanel/scripts/install_dovecot_fts'",
}
}
}
But when I run this in dev node I get error:
root#webcloud2 [/home1]# puppet agent -t --no-use_srv_records --server=puppet.development.internal --environment=testing --tags=cpanel::solr
Info: Retrieving pluginfacts
Info: Retrieving plugin
Info: Loading facts
2018-08-03 6:04:54 140004666824672 [Note] libgovernor.so found
2018-08-03 6:04:54 140004666824672 [Note] All governors functions found too
2018-08-03 6:04:54 140004666824672 [Note] Governor connected
2018-08-03 6:04:54 140004666824672 [Note] All governors lve functions found too
Error: Could not retrieve catalog from remote server: Error 400 on SERVER: keys(): Requires hash to work with at
/etc/puppet/environments/testing/modules/cpanel/manifests/solr.pp:6 on node webcloud2.development.internal
Warning: Not using cache on failed catalog
Error: Could not retrieve catalog; skipping run
What's wrong?
You have at least two problems there.
First problem is $home won't be set at all in that context. You would need to rewrite as:
class cpanel::solr(
$solr_enable = hiera('solr_enabled',false),
$homes = hiera_hash('fstab_homes', false),
)
{
$homes_keys = keys($homes)
...
}
Second problem is that your YAML isn't correctly indented, so fstab_homes would not actually return a Hash. It should be:
fstab_homes:
'/home1':
device: 'UUID=ac2ca97e-8bce-4774-92d7-051482253089'
'/home2':
device: 'UUID=d9daaeed-4e4e-40e9-aa6b-73632795e661'
'/home3':
device: 'UUID=21a358cf-2579-48cb-b89d-4ff43e4dd104'
'/home4':
device: 'UUID=c68041de-542a-4f72-9488-337048c41947'
'/home16':
device: 'UUID=d55eff53-3087-449b-9667-aeff49c556e7'
Finally, be aware that use of camelCase in parameter names in Puppet can cause you issues in some contexts, so best to use snake_case.

How can I write to TTY from a kernel module?

First post to SO, so I'll try to make the question right.
I'm making a simple Linux kernel module with the goal of echoing data back to the TTY shell from where the kernel module was loaded. The problem I having is the kernel "Ooops"-ing with the following message (caught with " watch 'dmesg | tail -50' "). The kernel module's name is Seraphim:
[ 184.222748] SELinux: initialized (dev proc, type proc), uses genfs_contexts
[ 1877.456607] seraphim: module verification failed: signature and/or required key missing - tainting kernel
[ 1877.457321] ------------------
[ 1877.457324] Seraphim started.
[ 1877.457348] BUG: unable to handle kernel NULL pointer dereference at 0000000000000218
[ 1877.457411] IP: [<ffffffffa0012030>] seraphim_entry+0x30/0x1000 [seraphim]
[ 1877.457462] PGD 115a2e067 PUD 10aca8067 PMD 0
[ 1877.457498] Oops: 0000 [#1] SMP
[ 1877.457524] Modules linked in: seraphim(OF+) rfcomm bnep nf_conntrack_netbios_ns nf_conn track_broadcast ipt_MASQUERADE ip6t_REJECT xt_conntrack ebtable_nat ebtable_broute bridge stp llce btable_filter ebtables ip6table_nat nf_conntrack_ipv6 nf_defrag_ipv6 nf_nat_ipv6 ip6table_ma etc.
The code used for writing data to the TTY terminal follows:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/tty.h>
static void printString(char *string) {
struct tty_struct *tty;
tty = current->signal->tty;
if(tty != NULL) {
(tty->driver->ops->write) (tty, string, strlen(string));
}
else
printk("tty equals to zero");
}
What am I doing wrong?
I was following the tutorial at http://www.tldp.org/LDP/lkmpg/2.6/lkmpg.pdf but it was out of date (the kernel I am using is 3.11.10-200 on Fedora 19), so I had to rummage through 3.11.10-200 source files to find the adequate structures.
use tty = get_current_tty(); instead of tty = current->signal->tty;
that's it
you need to lock the tty before accessing it and get_current_tty does it internally
NOTE: get_current_tty is under EXPORT_SYMBOL_GPL, hence your module or code

Resources