mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Complete removal of mount helper
This commit is contained in:
parent
220fc31605
commit
9b7ee8c924
@ -6,7 +6,7 @@ __license__ = 'GPL v3'
|
||||
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import sys, os, textwrap, subprocess, shutil, tempfile, atexit, stat, shlex
|
||||
import sys, os, textwrap, subprocess, shutil, tempfile, atexit, shlex
|
||||
|
||||
from setup import (Command, islinux, isbsd, basenames, modules, functions,
|
||||
__appname__, __version__)
|
||||
@ -168,10 +168,6 @@ class Develop(Command):
|
||||
ret = p.wait()
|
||||
if ret != 0:
|
||||
return warn()
|
||||
if not isbsd:
|
||||
os.chown(dest, 0, 0)
|
||||
os.chmod(dest, stat.S_ISUID|stat.S_ISGID|stat.S_IRUSR|stat.S_IWUSR|\
|
||||
stat.S_IXUSR|stat.S_IXGRP|stat.S_IXOTH)
|
||||
self.manifest.append(dest)
|
||||
return dest
|
||||
|
||||
|
@ -138,15 +138,10 @@ class LinuxFreeze(Command):
|
||||
|
||||
def compile_mount_helper(self):
|
||||
self.info('Compiling mount helper...')
|
||||
self.regain_privileges()
|
||||
dest = self.j(self.bin_dir, 'calibre-mount-helper')
|
||||
subprocess.check_call(['gcc', '-Wall', '-pedantic',
|
||||
self.j(self.SRC, 'calibre', 'devices',
|
||||
'linux_mount_helper.c'), '-o', dest])
|
||||
os.chown(dest, 0, 0)
|
||||
os.chmod(dest, stat.S_ISUID|stat.S_ISGID|stat.S_IRUSR|stat.S_IWUSR|\
|
||||
stat.S_IXUSR|stat.S_IXGRP|stat.S_IXOTH|stat.S_IRGRP|stat.S_IROTH)
|
||||
self.drop_privileges()
|
||||
|
||||
def copy_python(self):
|
||||
self.info('Copying python...')
|
||||
|
@ -1,323 +1,7 @@
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
#include <fcntl.h>
|
||||
#include <strings.h>
|
||||
|
||||
#define MARKER ".created_by_calibre_mount_helper"
|
||||
#define DEV "/dev/"
|
||||
#define MEDIA "/media/"
|
||||
#define False 0
|
||||
#define True 1
|
||||
|
||||
int exists(const char *path) {
|
||||
struct stat file_info;
|
||||
if (stat(path, &file_info) == 0) return True;
|
||||
return False;
|
||||
}
|
||||
|
||||
int get_root() {
|
||||
int res;
|
||||
res = setreuid(0, 0);
|
||||
if (res != 0) return False;
|
||||
if (setregid(0, 0) != 0) return False;
|
||||
return True;
|
||||
}
|
||||
|
||||
void ensure_root() {
|
||||
if (!get_root()) {
|
||||
fprintf(stderr, "Failed to get root.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
void check_mount_point(const char *mp) {
|
||||
|
||||
if (mp == NULL || strlen(mp) < strlen(MEDIA)) {
|
||||
fprintf(stderr, "Invalid arguments\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (strncmp(MEDIA, mp, strlen(MEDIA)) != 0) {
|
||||
fprintf(stderr, "Trying to operate on a mount point not under /media is not allowed\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int do_mount(const char *dev, const char *mp) {
|
||||
char options[1000], marker[2000];
|
||||
#ifdef __NetBSD__
|
||||
char uids[100], gids[100];
|
||||
#endif
|
||||
int errsv;
|
||||
|
||||
if (!exists(dev)) {
|
||||
fprintf(stderr, "Specified device node does not exist\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (!exists(mp)) {
|
||||
if (mkdir(mp, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) != 0) {
|
||||
errsv = errno;
|
||||
fprintf(stderr, "Failed to create mount point with error: %s\n", strerror(errsv));
|
||||
}
|
||||
}
|
||||
/* only mount if mp is under /media */
|
||||
mp = realpath(mp, NULL);
|
||||
if (mp == NULL) {
|
||||
fprintf(stderr, "realpath on mp failed.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (strncmp(MEDIA, mp, strlen(MEDIA)) != 0) {
|
||||
fprintf(stderr, "mount point is not under /media\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
snprintf(marker, 2000, "%s/%s", mp, MARKER);
|
||||
if (!exists(marker)) {
|
||||
int fd = creat(marker, S_IRUSR|S_IWUSR);
|
||||
if (fd == -1) {
|
||||
int errsv = errno;
|
||||
fprintf(stderr, "Failed to create marker with error: %s\n", strerror(errsv));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
#ifdef __NetBSD__
|
||||
snprintf(options, 1000, "rw,noexec,nosuid,sync,nodev");
|
||||
snprintf(uids, 100, "%d", getuid());
|
||||
snprintf(gids, 100, "%d", getgid());
|
||||
#else
|
||||
#ifdef __FreeBSD__
|
||||
snprintf(options, 1000, "rw,noexec,nosuid,sync,-u=%d,-g=%d",getuid(),getgid());
|
||||
#else
|
||||
snprintf(options, 1000, "rw,noexec,nosuid,sync,nodev,quiet,shortname=mixed,uid=%d,gid=%d,umask=077,fmask=0177,dmask=0077,utf8,iocharset=iso8859-1", getuid(), getgid());
|
||||
#endif
|
||||
#endif
|
||||
|
||||
ensure_root();
|
||||
|
||||
#ifdef __NetBSD__
|
||||
execlp("mount_msdos", "mount_msdos", "-u", uids, "-g", gids, "-o", options, dev, mp, NULL);
|
||||
#else
|
||||
#ifdef __FreeBSD__
|
||||
execlp("mount", "mount", "-t", "msdosfs", "-o", options, dev, mp, NULL);
|
||||
#else
|
||||
execlp("mount", "mount", "-t", "auto", "-o", options, dev, mp, NULL);
|
||||
#endif
|
||||
#endif
|
||||
errsv = errno;
|
||||
fprintf(stderr, "Failed to mount with error: %s\n", strerror(errsv));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
int call_eject(const char *dev, const char *mp) {
|
||||
int ret, pid, errsv, i, status = EXIT_FAILURE;
|
||||
|
||||
pid = fork();
|
||||
if (pid == -1) {
|
||||
fprintf(stderr, "Failed to fork\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (pid == 0) { /* Child process */
|
||||
ensure_root();
|
||||
#ifdef __NetBSD__
|
||||
execlp("eject", "eject", dev, NULL);
|
||||
#else
|
||||
#ifdef __FreeBSD__
|
||||
execlp("umount", "umount", dev, NULL);
|
||||
#else
|
||||
execlp("eject", "eject", "-s", dev, NULL);
|
||||
#endif
|
||||
#endif
|
||||
/* execlp failed */
|
||||
errsv = errno;
|
||||
fprintf(stderr, "Failed to eject with error: %s\n", strerror(errsv));
|
||||
exit(EXIT_FAILURE);
|
||||
} else { /* Parent */
|
||||
for (i = 0; i < 7; i++) {
|
||||
sleep(1);
|
||||
ret = waitpid(pid, &status, WNOHANG);
|
||||
if (ret == -1) return False;
|
||||
if (ret > 0) break;
|
||||
}
|
||||
return WIFEXITED(status) && WEXITSTATUS(status) == 0;
|
||||
}
|
||||
return False;
|
||||
}
|
||||
|
||||
int call_umount(const char *dev, const char *mp) {
|
||||
int ret, pid, errsv, i, status = EXIT_FAILURE;
|
||||
|
||||
pid = fork();
|
||||
if (pid == -1) {
|
||||
fprintf(stderr, "Failed to fork\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (pid == 0) { /* Child process */
|
||||
ensure_root();
|
||||
#ifdef __FreeBSD__
|
||||
execlp("umount", "umount", mp, NULL);
|
||||
#else
|
||||
execlp("umount", "umount", "-l", mp, NULL);
|
||||
#endif
|
||||
/* execlp failed */
|
||||
errsv = errno;
|
||||
fprintf(stderr, "Failed to umount with error: %s\n", strerror(errsv));
|
||||
exit(EXIT_FAILURE);
|
||||
} else { /* Parent */
|
||||
for (i = 0; i < 7; i++) {
|
||||
sleep(1);
|
||||
ret = waitpid(pid, &status, WNOHANG);
|
||||
if (ret == -1) return False;
|
||||
if (ret > 0) break;
|
||||
}
|
||||
return WIFEXITED(status) && WEXITSTATUS(status) == 0;
|
||||
}
|
||||
return False;
|
||||
}
|
||||
|
||||
int cleanup_mount_point(const char *mp) {
|
||||
char marker[2000];
|
||||
int urt, rmd, errsv;
|
||||
|
||||
snprintf(marker, 2000, "%s/%s", mp, MARKER);
|
||||
if (exists(marker)) {
|
||||
urt = unlink(marker);
|
||||
if (urt == -1) {
|
||||
errsv = errno;
|
||||
fprintf(stderr, "Failed to unlink marker: %s\n", strerror(errsv));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
rmd = rmdir(mp);
|
||||
if (rmd == -1) {
|
||||
errsv = errno;
|
||||
fprintf(stderr, "Failed to remove mount point: %s\n", strerror(errsv));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int do_eject(const char *dev, const char *mp) {
|
||||
int unmounted = False;
|
||||
|
||||
ensure_root();
|
||||
|
||||
unmounted = call_eject(dev, mp);
|
||||
if (!unmounted) call_umount(dev, mp);
|
||||
if (unmounted) return cleanup_mount_point(mp);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
int cleanup(const char *dev, const char *mp) {
|
||||
ensure_root();
|
||||
call_umount(dev, mp);
|
||||
return cleanup_mount_point(mp);
|
||||
}
|
||||
|
||||
void check_dev(const char *dev) {
|
||||
struct stat file_info;
|
||||
|
||||
if (dev == NULL || strlen(dev) < strlen(DEV)) {
|
||||
fprintf(stderr, "Invalid arguments\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (strncmp(DEV, dev, strlen(DEV)) != 0) {
|
||||
fprintf(stderr, "Trying to operate on a dev node not under /dev\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (stat(dev, &file_info) != 0) {
|
||||
fprintf(stderr, "stat call on dev node failed\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (strstr(dev, "/shm/") != NULL) {
|
||||
fprintf(stderr, "naughty, naughty!\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (!S_ISBLK(file_info.st_mode)) {
|
||||
fprintf(stderr, "dev node is not a block device\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
char *action, *dev, *mp, *temp;
|
||||
int status = EXIT_FAILURE;
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
/*printf("Real UID\t= %d\n", getuid());
|
||||
printf("Effective UID\t= %d\n", geteuid());
|
||||
printf("Real GID\t= %d\n", getgid());
|
||||
printf("Effective GID\t= %d\n", getegid());*/
|
||||
|
||||
if (argc != 4) {
|
||||
fprintf(stderr, "Needs 3 arguments: action, device node and mount point\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
action = argv[1]; dev = argv[2]; mp = argv[3];
|
||||
|
||||
/* Ensure that PATH only contains system directories to prevent execution of
|
||||
arbitrary executables as root */
|
||||
if (setenv("PATH",
|
||||
"/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin\0",
|
||||
1) != 0) {
|
||||
fprintf(stderr, "Failed to restrict PATH env var, aborting.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (strncmp(action, "mount", 5) == 0) {
|
||||
dev = realpath(argv[2], NULL);
|
||||
if (dev == NULL) {
|
||||
fprintf(stderr, "Failed to resolve device node.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
mp = get_real_mount_point(mp);
|
||||
check_dev(dev); check_mount_point(mp);
|
||||
status = do_mount(dev, mp);
|
||||
} else if (strncmp(action, "eject", 5) == 0) {
|
||||
dev = realpath(argv[2], NULL);
|
||||
if (dev == NULL) {
|
||||
fprintf(stderr, "Failed to resolve device node.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
temp = realpath(mp, NULL);
|
||||
if (temp == NULL) {
|
||||
fprintf(stderr, "Mount point does not exist\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
chdir(temp);
|
||||
check_dev(dev); check_mount_point(mp);
|
||||
status = do_eject(dev, mp);
|
||||
} else if (strncmp(action, "cleanup", 7) == 0) {
|
||||
temp = realpath(mp, NULL);
|
||||
if (temp == NULL) {
|
||||
fprintf(stderr, "Mount point does not exist\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
mp = temp;
|
||||
check_mount_point(mp);
|
||||
status = cleanup(dev, mp);
|
||||
} else {
|
||||
fprintf(stderr, "Unrecognized action: must be mount, eject or cleanup\n");
|
||||
}
|
||||
|
||||
return status;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -616,23 +616,11 @@ class Device(DeviceConfig, DevicePlugin):
|
||||
mount(node)
|
||||
return 0
|
||||
except:
|
||||
pass
|
||||
print 'Udisks mount call failed:'
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return 1
|
||||
|
||||
cmd = 'calibre-mount-helper'
|
||||
if getattr(sys, 'frozen', False):
|
||||
cmd = os.path.join(sys.executables_location, 'bin', cmd)
|
||||
cmd = [cmd, 'mount']
|
||||
mlabel = label
|
||||
if mlabel.endswith('/'):
|
||||
mlabel = mlabel[:-1]
|
||||
try:
|
||||
p = subprocess.Popen(cmd + [node, '/media/'+mlabel])
|
||||
except OSError:
|
||||
raise DeviceError(
|
||||
_('Could not find mount helper: %s.')%cmd[0])
|
||||
while p.poll() is None:
|
||||
time.sleep(0.1)
|
||||
return p.returncode
|
||||
|
||||
ret = do_mount(node, label)
|
||||
if ret != 0:
|
||||
@ -934,29 +922,12 @@ class Device(DeviceConfig, DevicePlugin):
|
||||
umount(d)
|
||||
except:
|
||||
pass
|
||||
failures = False
|
||||
for d in drives:
|
||||
try:
|
||||
eject(d)
|
||||
except Exception as e:
|
||||
print 'Udisks eject call for:', d, 'failed:'
|
||||
print '\t', e
|
||||
failures = True
|
||||
|
||||
if not failures:
|
||||
return
|
||||
|
||||
for drive in drives:
|
||||
cmd = 'calibre-mount-helper'
|
||||
if getattr(sys, 'frozen', False):
|
||||
cmd = os.path.join(sys.executables_location, 'bin', cmd)
|
||||
cmd = [cmd, 'eject']
|
||||
mp = getattr(self, "_linux_mount_map", {}).get(drive,
|
||||
'dummy/')[:-1]
|
||||
try:
|
||||
subprocess.Popen(cmd + [drive, mp]).wait()
|
||||
except:
|
||||
pass
|
||||
|
||||
def eject(self):
|
||||
if islinux:
|
||||
@ -982,19 +953,6 @@ class Device(DeviceConfig, DevicePlugin):
|
||||
self._main_prefix = self._card_a_prefix = self._card_b_prefix = None
|
||||
|
||||
def linux_post_yank(self):
|
||||
for drive, mp in getattr(self, '_linux_mount_map', {}).items():
|
||||
if drive and mp:
|
||||
mp = mp[:-1]
|
||||
cmd = 'calibre-mount-helper'
|
||||
if getattr(sys, 'frozen', False):
|
||||
cmd = os.path.join(sys.executables_location, 'bin', cmd)
|
||||
cmd = [cmd, 'cleanup']
|
||||
if mp and os.path.exists(mp):
|
||||
try:
|
||||
subprocess.Popen(cmd + [drive, mp]).wait()
|
||||
except:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
self._linux_mount_map = {}
|
||||
|
||||
def post_yank_cleanup(self):
|
||||
|
Loading…
x
Reference in New Issue
Block a user