Complete removal of mount helper

This commit is contained in:
Kovid Goyal 2011-11-05 06:51:15 +05:30
parent 220fc31605
commit 9b7ee8c924
4 changed files with 6 additions and 373 deletions

View File

@ -6,7 +6,7 @@ __license__ = 'GPL v3'
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>' __copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en' __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, from setup import (Command, islinux, isbsd, basenames, modules, functions,
__appname__, __version__) __appname__, __version__)
@ -168,10 +168,6 @@ class Develop(Command):
ret = p.wait() ret = p.wait()
if ret != 0: if ret != 0:
return warn() 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) self.manifest.append(dest)
return dest return dest

View File

@ -138,15 +138,10 @@ class LinuxFreeze(Command):
def compile_mount_helper(self): def compile_mount_helper(self):
self.info('Compiling mount helper...') self.info('Compiling mount helper...')
self.regain_privileges()
dest = self.j(self.bin_dir, 'calibre-mount-helper') dest = self.j(self.bin_dir, 'calibre-mount-helper')
subprocess.check_call(['gcc', '-Wall', '-pedantic', subprocess.check_call(['gcc', '-Wall', '-pedantic',
self.j(self.SRC, 'calibre', 'devices', self.j(self.SRC, 'calibre', 'devices',
'linux_mount_helper.c'), '-o', dest]) '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): def copy_python(self):
self.info('Copying python...') self.info('Copying python...')

View File

@ -1,323 +1,7 @@
#include <limits.h>
#include <stdlib.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) int main(int argc, char** argv)
{ {
char *action, *dev, *mp, *temp; return EXIT_FAILURE;
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;
} }

View File

@ -616,23 +616,11 @@ class Device(DeviceConfig, DevicePlugin):
mount(node) mount(node)
return 0 return 0
except: 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) ret = do_mount(node, label)
if ret != 0: if ret != 0:
@ -934,29 +922,12 @@ class Device(DeviceConfig, DevicePlugin):
umount(d) umount(d)
except: except:
pass pass
failures = False
for d in drives: for d in drives:
try: try:
eject(d) eject(d)
except Exception as e: except Exception as e:
print 'Udisks eject call for:', d, 'failed:' print 'Udisks eject call for:', d, 'failed:'
print '\t', e 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): def eject(self):
if islinux: if islinux:
@ -982,19 +953,6 @@ class Device(DeviceConfig, DevicePlugin):
self._main_prefix = self._card_a_prefix = self._card_b_prefix = None self._main_prefix = self._card_a_prefix = self._card_b_prefix = None
def linux_post_yank(self): 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 = {} self._linux_mount_map = {}
def post_yank_cleanup(self): def post_yank_cleanup(self):