Bug 846705 - udev rules MODE= does not change permissions
Summary: udev rules MODE= does not change permissions
Keywords:
Status: CLOSED NOTABUG
Alias: None
Product: Fedora
Classification: Fedora
Component: udev
Version: 17
Hardware: i686
OS: Linux
unspecified
medium
Target Milestone: ---
Assignee: udev-maint
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2012-08-08 13:21 UTC by Warren Jasper
Modified: 2012-08-08 22:36 UTC (History)
2 users (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2012-08-08 22:36:39 UTC
Type: Bug
Embargoed:


Attachments (Terms of Use)

Description Warren Jasper 2012-08-08 13:21:38 UTC
Description of problem:

With the new upgrade to udev, device nodes can no longer be renamed, only
network interfaces.  However, MODE= also no longer works to change the permission modes of a device.


Version-Release number of selected component (if applicable):


How reproducible:
Always

Steps to Reproduce:
1. I have a device PCI-DIO24 from Measurement Computing with an installed driver.  The driver creates the device node in /dev/dio24H

[root@tex-dragonlady1 pci-dio24]# ls -l /dev/dio24/
total 0
crw------- 1 root root 249, 0 Aug  6 10:18 dio0_0A
crw------- 1 root root 249, 1 Aug  6 10:18 dio0_0B
crw------- 1 root root 249, 2 Aug  6 10:18 dio0_0C

I would like to change the default permissions to 0666.


# /sbin/udevadm info -a -p $(/sbin/udevadm info -q path -n /dev/dio24/dio0_0A)

Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.

  looking at device '/devices/virtual/dio24/!dio24!dio0_0A':
    KERNEL=="/dio24/dio0_0A"
    SUBSYSTEM=="dio24"
    DRIVER==""


2.

I have a udev rule in /etc/udev/rules.d/60-mcc.rules

SUBSYSTEM=="dio24",      KERNEL=="/dio24/dio[0-9]_*",  MODE="0666"

3.
  
Actual results:
crw------- 1 root root 249, 0 Aug  6 10:18 dio0_0A

Expected results:
crw-rw-rw- 1 root root 249, 0 Aug  6 10:18 dio0_0A

Additional info:

Comment 1 Kay Sievers 2012-08-08 13:44:53 UTC
'/devices/virtual/dio24/!dio24!dio0_0A'

Awesome idea to start a device name with a '!'. That makes absolutely zero
sense. :)

> SUBSYSTEM=="dio24",      KERNEL=="/dio24/dio[0-9]_*",  MODE="0666"

I wouldn't be surprised if things go wrong with these unusual and kind
of broken device names. Wild guess, does it work if you remove the
KERNEL== match, and match only on the subsystem?

Comment 2 Warren Jasper 2012-08-08 15:16:38 UTC
I did not name the device as such.  Here is a snipit from the driver code
that creates the /sysfs entry:

  minor = (NumBoards<<0x4);
  sprintf(name, "/dio24/dio%d_0A", NumBoards);
  device_create(dio24_class, NULL, MKDEV(MajorNumber, minor), NULL, name);
  minor++;
  sprintf(name, "/dio24/dio%d_0B", NumBoards);
  device_create(dio24_class, NULL, MKDEV(MajorNumber, minor), NULL, name);
  minor++;
  sprintf(name, "/dio24/dio%d_0C", NumBoards);
  device_create(dio24_class, NULL, MKDEV(MajorNumber, minor), NULL, name);

Not sure where the '!' are coming from.  I also tried to match with just the
kernel, and also just SUBSYSTEM, but that does not work either.  From the
use of udevadm info above, I believe I should have a correct match with my
rule.

This whole thing came about because NAME=  is no longer a supported action
in udev in the new 3.0 Linux kernel.  IMHO that is the root cause of the bug.

To manage device nodes in a more sane hierarchical way, I created the 
"/dio24/dio%d_0A" entry in my driver.  Under 2.6, I could just use dio%d_OA 
and then use NAME="dio24/%k" to rename the device node, but that is broken under 3.0 kernel, as only interfaces can be renamed, not devices!

Comment 3 Kay Sievers 2012-08-08 17:39:40 UTC
(In reply to comment #2)
> I did not name the device as such.  Here is a snipit from the driver code
> that creates the /sysfs entry:
> 
>   minor = (NumBoards<<0x4);
>   sprintf(name, "/dio24/dio%d_0A", NumBoards);

There should be no leading /. All device names are relative to /dev.

> Not sure where the '!' are coming from.

The full device names appear as plain files in /sys, but '/' can obviously
not mapped to a file name, so it is replaced with '!' by the kernel's
driver core before the directory with that name is created in /sys.

> I also tried to match with just the
> kernel, and also just SUBSYSTEM, but that does not work either.  From the
> use of udevadm info above, I believe I should have a correct match with my
> rule.

Maybe try:
  udevadm test /sys/...
and check if it tells something.

> This whole thing came about because NAME=  is no longer a supported action
> in udev in the new 3.0 Linux kernel.  IMHO that is the root cause of the bug.

Yes, all device nodes are created by the kernel, not by udev. So it makes not
much sense for udev to mangle the kernel created device nodes. /dev and
/sys should have matching names, and not "abstractions and mappings" in udev.

Udev/userspace should only create additional symlinks, not device nodes these
days.

> To manage device nodes in a more sane hierarchical way, I created the 
> "/dio24/dio%d_0A" entry in my driver.  Under 2.6, I could just use dio%d_OA 
> and then use NAME="dio24/%k" to rename the device node, but that is broken
> under 3.0 kernel, as only interfaces can be renamed, not devices!

That sounds fine. You should probably drop the leading /, it likely confuses
tools.

Comment 4 Warren Jasper 2012-08-08 18:04:31 UTC
Well, device nodes may be created by the kernel, but /dev is in user space
not kernel space, so that is why udev was created in the first place.  I'm 
not here to argue this philisophical point, just to get udev to
behave in some rational manner so I can set the correct permissions.

I removed the leading "/" in my driver.  Now I get:

[root@tex-dragonlady1 pci-dio24]# ls -l /dev/dio24/
total 0
crw------- 1 root root 249, 0 Aug  8 13:51 dio0_0A
crw------- 1 root root 249, 1 Aug  8 13:51 dio0_0B
crw------- 1 root root 249, 2 Aug  8 13:51 dio0_0C

As before, but the following is different:

]# udevadm info --name=/dev/dio24/dio0_0A --attribute-walk

Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.

  looking at device '/devices/virtual/dio24/dio24!dio0_0A':
    KERNEL=="dio24/dio0_0A"
    SUBSYSTEM=="dio24"
    DRIVER==""


There is still a '!' for the subdirectory.  There is no other way I know to make
a subdirectory in Linux now that udev will not mangle NAMES of the device nodes.
udev still does not recognize the rule and change the permissions.  Any idea
how I can get a match to perform the MODE= action?

Comment 5 Kay Sievers 2012-08-08 19:04:19 UTC
(In reply to comment #4)
> Well, device nodes may be created by the kernel, but /dev is in user space
> not kernel space, so that is why udev was created in the first place.  I'm 
> not here to argue this philisophical point, just to get udev to
> behave in some rational manner so I can set the correct permissions.

Device and their names are managed in kernel space. The interface is
provided by the kernel. We created udev primarily to have a /dev that
reflects the kernel's state, not to be free to name devices in
userspace. The match between /dev/ and /sys and the kernel logs is in
most cases more important than rules giving custom names. Meaningful
names are all provides by symlinks to the primary nodes today.

>   looking at device '/devices/virtual/dio24/dio24!dio0_0A':
>     KERNEL=="dio24/dio0_0A"
>     SUBSYSTEM=="dio24"

> There is still a '!' for the subdirectory.

That looks fine.

> There is no other way I know to make
> a subdirectory in Linux now that udev will not mangle NAMES of the device
> nodes. 

You can provide a .devnode callback in the class, that names the devices of
a class:
  http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=drivers/input/input.c;h=8921c6180c51dfe0efadeef0e7be59878aeca252;hb=HEAD#l1627

> udev still does not recognize the rule and change the permissions.  Any idea
> how I can get a match to perform the MODE= action?

Did you try:
  udevadm test <devpath>?

Comment 6 Warren Jasper 2012-08-08 20:45:36 UTC
OK got it to work.  Forgot to take the leading / in my udev rules.
The following works:

  sprintf(name, "dio24/dio%d_0A", NumBoards);
  device_create(dio24_class, NULL, MKDEV(MajorNumber, minor), NULL, name);

with the corresponding udev rule:

SUBSYSTEM=="dio24",     KERNEL=="dio24/dio[0-9]_*",  MODE="666"


# ls -l /dev/dio24/
total 0
crw-rw-rw- 1 root root 249, 0 Aug  8 16:35 dio0_0A
crw-rw-rw- 1 root root 249, 1 Aug  8 16:35 dio0_0B
crw-rw-rw- 1 root root 249, 2 Aug  8 16:35 dio0_0C

# /sbin/udevadm info -a -p $(/sbin/udevadm info -q path -n /dev/dio24/dio0_0A)

Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.

  looking at device '/devices/virtual/dio24/dio24!dio0_0A':
    KERNEL=="dio24/dio0_0A"
    SUBSYSTEM=="dio24"
    DRIVER==""


Much thanks for your suggestions.

Comment 7 Kay Sievers 2012-08-08 22:36:39 UTC
Nice. Looks all fine.

If you ever want, you can get the same result in /dev, without the '!' tricks
in /sys by using a .devnode() callback like mentioned above. That's how sound,
input, usb, dvb, bsg, and most of the other stuff in the kernel, which has
subdirs in /dev, works. The KERNEL== match would not include the leading subdir
then.

But there is no need to change it, the '/' -> '!' logic will not go away.


Note You need to log in before you can comment on or make changes to this bug.