dvm: appvm side code
This commit is contained in:
parent
ede7fff0fd
commit
db8962f748
@ -1,9 +1,11 @@
|
||||
CC=gcc
|
||||
CFLAGS=-Wall
|
||||
all: qubes_penctl qubes_add_pendrive_script
|
||||
all: qubes_penctl qubes_add_pendrive_script qvm-open-in-dvm
|
||||
qubes_penctl: qubes_penctl.o
|
||||
$(CC) -o qubes_penctl qubes_penctl.o -lxenstore
|
||||
qubes_add_pendrive_script: qubes_add_pendrive_script.o
|
||||
$(CC) -o qubes_add_pendrive_script qubes_add_pendrive_script.o
|
||||
$(CC) -o qubes_add_pendrive_script qubes_add_pendrive_script.o -lxenstore
|
||||
qvm-open-in-dvm: qvm-open-in-dvm.o
|
||||
$(CC) -o qvm-open-in-dvm qvm-open-in-dvm.o -lxenstore
|
||||
clean:
|
||||
rm -f qubes_penctl qubes_add_pendrive_script *.o *~
|
||||
rm -f qubes_penctl qubes_add_pendrive_script qvm-open-in-dvm *.o *~
|
||||
|
6
appvm/dvm.h
Normal file
6
appvm/dvm.h
Normal file
@ -0,0 +1,6 @@
|
||||
#define DBDIR "/home/user/.dvm"
|
||||
struct dvm_header {
|
||||
unsigned long long file_size;
|
||||
char name[1024-sizeof(unsigned long long)];
|
||||
};
|
||||
|
@ -18,17 +18,25 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/inotify.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <xs.h>
|
||||
#include <syslog.h>
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
#include "dvm.h"
|
||||
|
||||
int parse_events(char *buf, int len)
|
||||
{
|
||||
int i = 0;
|
||||
while (i < len) {
|
||||
struct inotify_event *ev = (struct inotify_event *)(buf + i);
|
||||
struct inotify_event *ev =
|
||||
(struct inotify_event *) (buf + i);
|
||||
if ((ev->mask & IN_UNMOUNT) || (ev->mask & IN_IGNORED))
|
||||
return 1;
|
||||
i += sizeof(struct inotify_event) + ev->len;
|
||||
@ -69,19 +77,177 @@ void background()
|
||||
switch (fork()) {
|
||||
case -1:
|
||||
exit(1);
|
||||
case 0: break;
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
void check_legal_filename(char *name)
|
||||
{
|
||||
if (index(name, '/')) {
|
||||
syslog(LOG_DAEMON | LOG_ERR,
|
||||
"the received filename contains /");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void drop_to_user()
|
||||
{
|
||||
struct passwd *pw = getpwnam("user");
|
||||
if (pw)
|
||||
setuid(pw->pw_uid);
|
||||
}
|
||||
|
||||
void copy_from_xvdh(int destfd, int srcfd, unsigned long long count)
|
||||
{
|
||||
int n, size;
|
||||
char buf[4096];
|
||||
unsigned long long total = 0;
|
||||
while (total < count) {
|
||||
if (count - total > sizeof(buf))
|
||||
size = sizeof(buf);
|
||||
else
|
||||
size = count - total;
|
||||
n = read(srcfd, buf, size);
|
||||
if (n != size) {
|
||||
syslog(LOG_DAEMON | LOG_ERR, "reading xvdh");
|
||||
exit(1);
|
||||
}
|
||||
if (write(destfd, buf, size) != size) {
|
||||
syslog(LOG_DAEMON | LOG_ERR, "writing file");
|
||||
exit(1);
|
||||
}
|
||||
total += size;
|
||||
}
|
||||
}
|
||||
|
||||
void redirect_stderr()
|
||||
{
|
||||
int fd =
|
||||
open("/var/log/dvm.log", O_CREAT | O_TRUNC | O_WRONLY, 0600);
|
||||
if (fd < 0) {
|
||||
syslog(LOG_DAEMON | LOG_ERR, "open dvm.log");
|
||||
exit(1);
|
||||
}
|
||||
dup2(fd, 2);
|
||||
}
|
||||
|
||||
void dvm_transaction_request(char *seq, struct xs_handle *xs)
|
||||
{
|
||||
char filename[1024], cmdbuf[1024];
|
||||
struct dvm_header header;
|
||||
int xvdh_fd, file_fd;
|
||||
char *src_vm;
|
||||
unsigned int len;
|
||||
xvdh_fd = open("/dev/xvdh", O_RDONLY);
|
||||
if (read(xvdh_fd, &header, sizeof(header)) != sizeof(header)) {
|
||||
syslog(LOG_DAEMON | LOG_ERR, "read dvm_header");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
header.name[sizeof(header.name) - 1] = 0;
|
||||
check_legal_filename(header.name);
|
||||
snprintf(filename, sizeof(filename), "/tmp/%s", header.name);
|
||||
drop_to_user();
|
||||
|
||||
file_fd = open(filename, O_CREAT | O_TRUNC | O_WRONLY, 0600);
|
||||
if (file_fd < 0) {
|
||||
syslog(LOG_DAEMON | LOG_ERR, "open file");
|
||||
exit(1);
|
||||
}
|
||||
copy_from_xvdh(file_fd, xvdh_fd, header.file_size);
|
||||
close(xvdh_fd);
|
||||
close(file_fd);
|
||||
snprintf(cmdbuf, sizeof(cmdbuf),
|
||||
"DISPLAY=:0 mimeopen -n '/tmp/%s'", header.name);
|
||||
system(cmdbuf);
|
||||
src_vm = xs_read(xs, XBT_NULL, "qubes_blocksrc", &len);
|
||||
xs_write(xs, XBT_NULL, "device/qpen", "umount", 6);
|
||||
xs_daemon_close(xs);
|
||||
execl("/usr/bin/qvm-dvm-transfer", "qvm-dvm-transfer", src_vm,
|
||||
filename, seq, NULL);
|
||||
syslog(LOG_DAEMON | LOG_ERR, "execl qvm-dvm-transfer");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void dvm_transaction_return(char *seq_string, struct xs_handle *xs)
|
||||
{
|
||||
int seq = strtoul(seq_string, 0, 10);
|
||||
char db_name[1024];
|
||||
char file_name[1024];
|
||||
int db_fd, file_fd, xvdh_fd;
|
||||
|
||||
struct dvm_header header;
|
||||
xvdh_fd = open("/dev/xvdh", O_RDONLY);
|
||||
if (xvdh_fd < 0) {
|
||||
syslog(LOG_DAEMON | LOG_ERR, "open xvdh");
|
||||
exit(1);
|
||||
}
|
||||
if (read(xvdh_fd, &header, sizeof(header)) != sizeof(header)) {
|
||||
syslog(LOG_DAEMON | LOG_ERR, "read dvm_header");
|
||||
exit(1);
|
||||
}
|
||||
drop_to_user();
|
||||
snprintf(db_name, sizeof(db_name), DBDIR "/%d", seq);
|
||||
db_fd = open(db_name, O_RDONLY);
|
||||
if (!db_fd) {
|
||||
syslog(LOG_DAEMON | LOG_ERR, "open db");
|
||||
exit(1);
|
||||
}
|
||||
if (read(db_fd, file_name, sizeof(file_name)) < 0) {
|
||||
syslog(LOG_DAEMON | LOG_ERR, "read db");
|
||||
exit(1);
|
||||
}
|
||||
close(db_fd);
|
||||
file_fd = open(file_name, O_WRONLY | O_TRUNC);
|
||||
if (file_fd < 0) {
|
||||
syslog(LOG_DAEMON | LOG_ERR, "open filename");
|
||||
exit(1);
|
||||
}
|
||||
copy_from_xvdh(file_fd, xvdh_fd, header.file_size);
|
||||
close(xvdh_fd);
|
||||
close(file_fd);
|
||||
xs_write(xs, XBT_NULL, "device/qpen", "umount", 6);
|
||||
xs_daemon_close(xs);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void dvm_transaction(char *seq, struct xs_handle *xs)
|
||||
{
|
||||
struct stat st;
|
||||
redirect_stderr();
|
||||
if (stat("/etc/this_is_dvm", &st))
|
||||
dvm_transaction_return(seq, xs);
|
||||
else
|
||||
dvm_transaction_request(seq, xs);
|
||||
}
|
||||
|
||||
#define MOUNTDIR "/mnt/incoming"
|
||||
int main()
|
||||
{
|
||||
struct xs_handle *xs;
|
||||
char *seq;
|
||||
unsigned int len;
|
||||
background();
|
||||
openlog("qubes_add_pendrive_script", LOG_CONS | LOG_PID,
|
||||
LOG_DAEMON);
|
||||
xs = xs_domain_open();
|
||||
if (!xs) {
|
||||
syslog(LOG_DAEMON | LOG_ERR, "xs_domain_open");
|
||||
exit(1);
|
||||
}
|
||||
seq = xs_read(xs, XBT_NULL, "qubes_transaction_seq", &len);
|
||||
if (seq && len > 0 && strcmp(seq, "0")) {
|
||||
dvm_transaction(seq, xs);
|
||||
exit(0);
|
||||
}
|
||||
if (!system("su - user -c 'mount " MOUNTDIR "'"))
|
||||
wait_for_umount(MOUNTDIR "/.");
|
||||
system("xenstore-write device/qpen umount");
|
||||
xs_write(xs, XBT_NULL, "device/qpen", "umount", 6);
|
||||
xs_daemon_close(xs);
|
||||
return 0;
|
||||
}
|
||||
|
176
appvm/qvm-open-in-dvm.c
Normal file
176
appvm/qvm-open-in-dvm.c
Normal file
@ -0,0 +1,176 @@
|
||||
/*
|
||||
* The Qubes OS Project, http://www.qubes-os.org
|
||||
*
|
||||
* Copyright (C) 2010 Rafal Wojtczuk <rafal@invisiblethingslab.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
#define _GNU_SOURCE
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <xs.h>
|
||||
#include "dvm.h"
|
||||
|
||||
void check_name(unsigned char *s)
|
||||
{
|
||||
int c;
|
||||
for (; *s; s++) {
|
||||
c = *s;
|
||||
if (c >= 'a' && c <= 'z')
|
||||
continue;
|
||||
if (c >= 'A' && c <= 'Z')
|
||||
continue;
|
||||
if (c == '_' || c == '-')
|
||||
continue;
|
||||
fprintf(stderr, "invalid string %s\n", s);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int get_and_set_seq()
|
||||
{
|
||||
int seq_fd, seq, n;
|
||||
mkdir(DBDIR, 0700);
|
||||
seq_fd = open(DBDIR "/seq", O_CREAT | O_RDWR, 0600);
|
||||
if (seq_fd < 0) {
|
||||
perror("open seq_fd");
|
||||
exit(1);
|
||||
}
|
||||
n = read(seq_fd, &seq, sizeof(seq));
|
||||
if (n < sizeof(seq))
|
||||
seq = 0;
|
||||
seq++;
|
||||
lseek(seq_fd, 0, SEEK_SET);
|
||||
write(seq_fd, &seq, sizeof(seq));
|
||||
close(seq_fd);
|
||||
return seq;
|
||||
}
|
||||
|
||||
void write_db(char *name, int seq)
|
||||
{
|
||||
int db_fd;
|
||||
char dbname[256];
|
||||
struct stat st;
|
||||
if (!stat("/etc/this_is_dvm", &st))
|
||||
return;
|
||||
snprintf(dbname, sizeof(dbname), DBDIR "/%d", seq);
|
||||
db_fd = open(dbname, O_CREAT | O_WRONLY | O_TRUNC, 0600);
|
||||
if (db_fd < 0) {
|
||||
perror("open dbfile");
|
||||
exit(1);
|
||||
}
|
||||
if (write(db_fd, name, strlen(name) + 1) != strlen(name) + 1) {
|
||||
perror("write db");
|
||||
exit(1);
|
||||
}
|
||||
close(db_fd);
|
||||
}
|
||||
|
||||
void copy_file(int xvdg_fd, int file_fd)
|
||||
{
|
||||
int n;
|
||||
char buf[4096];
|
||||
|
||||
for (;;) {
|
||||
n = read(file_fd, buf, sizeof(buf));
|
||||
if (n < 0) {
|
||||
perror("read file");
|
||||
exit(1);
|
||||
}
|
||||
if (n == 0)
|
||||
break;
|
||||
if (write(xvdg_fd, buf, n) != n) {
|
||||
perror("write file");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct dvm_header header = { 0, };
|
||||
struct stat st;
|
||||
struct xs_handle *xs;
|
||||
int seq;
|
||||
int xvdg_fd, file_fd;
|
||||
char *abs_filename;
|
||||
char buf[4096];
|
||||
|
||||
if (argc != 3 && argc != 4) {
|
||||
fprintf(stderr, "usage: %s vmname file\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
check_name((unsigned char *) argv[1]);
|
||||
if (argv[2][0] == '/')
|
||||
abs_filename = argv[2];
|
||||
else {
|
||||
char cwd[4096];
|
||||
getcwd(cwd, sizeof(cwd));
|
||||
asprintf(&abs_filename, "%s/%s", cwd, argv[2]);
|
||||
}
|
||||
if (stat(abs_filename, &st)) {
|
||||
perror("stat file");
|
||||
exit(1);
|
||||
}
|
||||
header.file_size = st.st_size;
|
||||
strncpy(header.name, rindex(abs_filename, '/') + 1,
|
||||
sizeof(header.name) - 1);
|
||||
xs = xs_domain_open();
|
||||
if (!xs) {
|
||||
perror("xs_domain_open");
|
||||
exit(1);
|
||||
}
|
||||
if (!xs_write(xs, 0, "device/qpen", "new", 3)) {
|
||||
perror("xs_write");
|
||||
exit(1);
|
||||
}
|
||||
while (stat("/dev/xvdg", &st))
|
||||
usleep(100000);
|
||||
xvdg_fd = open("/dev/xvdg", O_WRONLY);
|
||||
if (xvdg_fd < 0) {
|
||||
perror("open xvdg");
|
||||
exit(1);
|
||||
}
|
||||
setuid(getuid());
|
||||
if (argc == 3)
|
||||
seq = get_and_set_seq();
|
||||
else
|
||||
seq = strtoul(argv[3], 0, 0);
|
||||
file_fd = open(abs_filename, O_RDONLY);
|
||||
if (file_fd < 0) {
|
||||
perror("open file");
|
||||
exit(1);
|
||||
}
|
||||
if (write(xvdg_fd, &header, sizeof(header)) != sizeof(header)) {
|
||||
perror("write filesize");
|
||||
exit(1);
|
||||
}
|
||||
copy_file(xvdg_fd, file_fd);
|
||||
close(file_fd);
|
||||
close(xvdg_fd);
|
||||
snprintf(buf, sizeof(buf), "send %s %d", argv[1], seq);
|
||||
if (!xs_write(xs, 0, "device/qpen", buf, strlen(buf))) {
|
||||
perror("xs_write");
|
||||
exit(1);
|
||||
}
|
||||
write_db(abs_filename, seq);
|
||||
xs_daemon_close(xs);
|
||||
return 0;
|
||||
}
|
@ -60,7 +60,10 @@ mkdir -p $RPM_BUILD_ROOT/etc/init.d
|
||||
cp qubes_core $RPM_BUILD_ROOT/etc/init.d/
|
||||
mkdir -p $RPM_BUILD_ROOT/var/lib/qubes
|
||||
mkdir -p $RPM_BUILD_ROOT/usr/bin
|
||||
cp qubes_timestamp qubes_add_pendrive_script qubes_penctl qvm-copy-to-vm qvm-copy-to-vm.kde $RPM_BUILD_ROOT/usr/bin
|
||||
cp qubes_timestamp qubes_add_pendrive_script qubes_penctl \
|
||||
qvm-copy-to-vm qvm-copy-to-vm.kde \
|
||||
qvm-open-in-dvm $RPM_BUILD_ROOT/usr/bin
|
||||
ln -s qvm-open-in-dvm $RPM_BUILD_ROOT/usr/bin/qvm-dvm-transfer
|
||||
mkdir -p $RPM_BUILD_ROOT/%{kde_service_dir}
|
||||
cp qvm-copy.desktop $RPM_BUILD_ROOT/%{kde_service_dir}
|
||||
mkdir -p $RPM_BUILD_ROOT/etc/udev/rules.d
|
||||
@ -178,6 +181,8 @@ rm -rf $RPM_BUILD_ROOT
|
||||
/etc/init.d/qubes_core
|
||||
/usr/bin/qvm-copy-to-vm
|
||||
/usr/bin/qvm-copy-to-vm.kde
|
||||
%attr(4755,root,root) /usr/bin/qvm-open-in-dvm
|
||||
/usr/bin/qvm-dvm-transfer
|
||||
%{kde_service_dir}/qvm-copy.desktop
|
||||
%attr(4755,root,root) /usr/bin/qubes_penctl
|
||||
/usr/bin/qubes_add_pendrive_script
|
||||
|
Loading…
Reference in New Issue
Block a user