[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#1091448: linux: CDROM_LOCKDOOR does not lock the door



Package: src:linux
Version: 5.10.226-1
Severity: normal
X-Debbugs-Cc: tg@mirbsd.de

I wrote a program to run…
	ioctl(i, CDROM_LOCKDOOR, 1)
… on /dev/cdrom aka /dev/sr0, and it executes correctly.
The program then holds the file descriptor open until SIGTERM.

However, the only effect of this is that /dev/cdrom and the other
/dev/cd-something symlink I cannot remember go away. The CD-ROM
drive is not locked.

This is on a Thinkpad X61, CD-ROM drive in docking station.

Not sure whether the model just cannot do this or udev is interfering
or something else is going on, but, for comparison, on a Thinkpad X40
(i.e. a pretty similar setup) the equivalent ioctl on MirBSD can indeed
successfully lock the drive, so at least it’s not a systematic problem
with Thinkpads.

I’m attaching a first draft (I didn’t have the tuits to fully port
cdio(1) with all of its features at the moment).

-- Package-specific info:
** Version:
Linux version 5.10.0-33-amd64 (debian-kernel@lists.debian.org) (gcc-10 (Debian 10.2.1-6) 10.2.1 20210110, GNU ld (GNU Binutils for Debian) 2.35.2) #1 SMP Debian 5.10.226-1 (2024-10-03)

** Command line:
BOOT_IMAGE=/vmlinuz-5.10.0-33-amd64 root=/dev/mapper/vg--x61p-lv--root ro net.ifnames=0 rootflags=defaults,relatime,lazytime,barrier=1,data=ordered,auto_da_alloc vga=792 TZ=:Europe/Berlin

** Tainted: OE (12288)
 * externally-built ("out-of-tree") module was loaded
 * unsigned module was loaded

** Kernel log:
Unable to read kernel log; any relevant messages should be attached

** Model information
sys_vendor: LENOVO
product_name: 7674D67
product_version: ThinkPad X61
chassis_vendor: LENOVO
chassis_version: Not Available
bios_vendor: LENOVO
bios_version: 7NET30WW (1.11 )
board_vendor: LENOVO
board_name: 7674D67
board_version: Not Available

** Loaded modules:
snd_seq_dummy
snd_seq
snd_seq_device
fuse
cpufreq_ondemand
ctr
ccm
binfmt_misc
cpufreq_powersave
tp_smapi(OE)
thinkpad_ec(OE)
msr
snd_hda_codec_analog
snd_hda_codec_generic
iwl4965
iwlegacy
snd_hda_intel
mac80211
i915
snd_intel_dspcfg
coretemp
soundwire_intel
pcmcia
soundwire_generic_allocation
snd_soc_core
snd_compress
kvm_intel
soundwire_cadence
snd_hda_codec
cfg80211
snd_hda_core
drm_kms_helper
cec
kvm
snd_hwdep
ppdev
drm
soundwire_bus
iTCO_wdt
intel_pmc_bxt
yenta_socket
irqbypass
evdev
thinkpad_acpi
pcmcia_rsrc
snd_pcm
iTCO_vendor_support
pcmcia_core
watchdog
serio_raw
libarc4
pcspkr
i2c_algo_bit
nvram
sg
snd_timer
ledtrig_audio
snd
soundcore
rfkill
parport_pc
ac
parport
button
acpi_cpufreq
ecb
aes_generic
libaes
crypto_simd
cryptd
glue_helper
xts
dm_crypt
dm_mod
ext4
crc16
mbcache
jbd2
crc32c_generic
mmc_block
sd_mod
t10_pi
crc_t10dif
crct10dif_generic
sr_mod
cdrom
crct10dif_common
sdhci_pci
ata_generic
cqhci
e1000e
ahci
ehci_pci
uhci_hcd
ehci_hcd
libahci
sdhci
i2c_i801
ptp
ata_piix
libata
psmouse
usbcore
pps_core
scsi_mod
mmc_core
lpc_ich
i2c_smbus
usb_common
battery
video

** PCI devices:
not available

** USB devices:
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 006 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 001 Device 003: ID 17ef:1000 Lenovo ThinkPad X6 UltraBase
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 002 Device 002: ID 0483:2016 STMicroelectronics Fingerprint Reader
Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub


-- System Information:
Debian Release: 11.11
  APT prefers oldstable-updates
  APT policy: (500, 'oldstable-updates'), (500, 'oldstable-security'), (500, 'oldstable')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 5.10.0-33-amd64 (SMP w/2 CPU threads)
Kernel taint flags: TAINT_OOT_MODULE, TAINT_UNSIGNED_MODULE
Locale: LANG=C.UTF-8, LC_CTYPE=C.UTF-8 (charmap=UTF-8), LANGUAGE not set
Shell: /bin/sh linked to /bin/lksh
Init: sysvinit (via /sbin/init)

Versions of packages linux-image-5.10.0-33-amd64 depends on:
ii  initramfs-tools [linux-initramfs-tool]  0.140
ii  kmod                                    28-1
ii  linux-base                              4.6

Versions of packages linux-image-5.10.0-33-amd64 recommends:
pn  apparmor             <none>
ii  firmware-linux-free  20200122-1

Versions of packages linux-image-5.10.0-33-amd64 suggests:
pn  debian-kernel-handbook  <none>
ii  grub-pc                 2.06-3~deb11u6
pn  linux-doc-5.10          <none>

Versions of packages linux-image-5.10.0-33-amd64 is related to:
pn  firmware-amd-graphics     <none>
pn  firmware-atheros          <none>
pn  firmware-bnx2             <none>
pn  firmware-bnx2x            <none>
pn  firmware-brcm80211        <none>
pn  firmware-cavium           <none>
pn  firmware-intel-sound      <none>
pn  firmware-intelwimax       <none>
pn  firmware-ipw2x00          <none>
pn  firmware-ivtv             <none>
ii  firmware-iwlwifi          20210315-3
pn  firmware-libertas         <none>
pn  firmware-linux-nonfree    <none>
pn  firmware-misc-nonfree     <none>
pn  firmware-myricom          <none>
pn  firmware-netxen           <none>
pn  firmware-qlogic           <none>
pn  firmware-realtek          <none>
pn  firmware-samsung          <none>
pn  firmware-siano            <none>
pn  firmware-ti-connectivity  <none>
pn  xen-hypervisor            <none>

-- no debconf information
/* SPDX-License-Identifier: MirOS OR CC0-1.0 */
/* © 2024 mirabilos Ⓕ MirBSD or CC0 */

#include <sys/types.h>
#include <sys/ioctl.h>
#include <linux/cdrom.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>

#if 0
#define DEFAULT_CDROM "/dev/cdrom"
#else
/* udev, on 'cdio lock', drops /dev/cd* entries; gotta love progress! */
#define DEFAULT_CDROM "/dev/sr0"
#endif

enum command {
	CMD_CLOSE,
	CMD_EJECT,
	CMD_LOCK,
};

static volatile sig_atomic_t keeprunning;
/* pointer, not array */
static const char *dvname = DEFAULT_CDROM;

static void initsigs(void);
static void usage(void) __attribute__((__noreturn__));

int
main(int argc, char *argv[])
{
	int i;
	enum command cmd;

	while ((i = getopt(argc, argv, "d:f:sv")) != -1)
		switch (i) {
		case 'd':
		case 's':
		case 'v':
			/* ignored, for MirBSD cdio(1) compatibility */
			break;
		case 'f':
			dvname = optarg;
			break;
		default:
			usage();
		}
	argc -= optind;
	argv += optind;

	if (argc != 1) /* for now */
		usage();
	if (!strcmp(*argv, "close"))
		cmd = CMD_CLOSE;
	else if (!strcmp(*argv, "eject"))
		cmd = CMD_EJECT;
	else if (!strcmp(*argv, "lock"))
		cmd = CMD_LOCK;
	else
		usage();

	/* O_NONBLOCK per <linux/cdrom.h> instructions */
	if ((i = open(dvname, O_RDONLY | O_NONBLOCK)) == -1)
		err(1, "open %s", dvname);
#define tryioctl(name, ...) do {				\
	/* as unknown error indicator */			\
	errno = ENOPROTOOPT;					\
	if (ioctl(i, name, ## __VA_ARGS__) < 0)			\
		err(1, "ioctl(%s, %s)", dvname, #name);		\
} while (/* CONSTCOND */ 0)
	switch (cmd) {
	case CMD_CLOSE:
		if (ioctl(i, CDROMCLOSETRAY, 0) < 0)
			err(1, "ioctl(%s, %s)", dvname, "CDROMCLOSETRAY");
		break;
	case CMD_EJECT:
		/* try unlocking first */
		if (ioctl(i, CDROM_LOCKDOOR, 0) < 0)
			warn("ioctl(%s, %s)", dvname, "CDROM_LOCKDOOR");
		errno = ENOPROTOOPT;
		if (ioctl(i, CDROMEJECT, 0) < 0)
			err(1, "ioctl(%s, %s)", dvname, "CDROMEJECT");
		break;
	case CMD_LOCK:
		if (ioctl(i, CDROM_LOCKDOOR, 1) < 0)
			err(1, "ioctl(%s, %s)", dvname, "CDROM_LOCKDOOR");
		/* assert(!is_interactive); */
		initsigs();
		printf("I: locked; keeping program running until aborted...");
		fflush(NULL);
		keeprunning = 1;
		while (keeprunning)
			pause();
		printf("\nI: signal caught, exiting\n");
		break;
	}
	close(i);
	return (0);
}

static void
usage(void)
{
	fprintf(stderr, "E: usage: cdio [-f %s] <command>\n", DEFAULT_CDROM);
	fprintf(stderr, "N: commands are: close eject lock\n");
	exit(1);
}

static void
handle_sigterm(int signo __attribute__((__unused__)))
{
	keeprunning = 0;
}

static void
initsigs(void)
{
	struct sigaction sa;

	memset(&sa, '\0', sizeof(sa));
	sa.sa_handler = &handle_sigterm;
	sigemptyset(&sa.sa_mask);
	sa.sa_flags = SA_RESETHAND;
	if (sigaction(SIGTERM, &sa, NULL))
		warn("could not install SIGTERM handler");
}

Reply to: