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>'
__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

View File

@ -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...')

View File

@ -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;
}

View File

@ -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):