上星期六陪我爸去了在San Mateo的工展會,去到後才發覺其實不外如是。工展會,應該是工商業展覽會吧,但跟本沒展覽了甚麽東西,除了這個非賣品:
說真的,那是最受五六歲以下小朋友歡迎的東西了。
那最受其他人歡迎的呢?莫過於大大小小的遊戲攤擋了。比如這部搶錢機:
原來玩遊戲也可以買五送一的:
這就叫工展會?
上星期六陪我爸去了在San Mateo的工展會,去到後才發覺其實不外如是。工展會,應該是工商業展覽會吧,但跟本沒展覽了甚麽東西,除了這個非賣品:
說真的,那是最受五六歲以下小朋友歡迎的東西了。
那最受其他人歡迎的呢?莫過於大大小小的遊戲攤擋了。比如這部搶錢機:
原來玩遊戲也可以買五送一的:
這就叫工展會?
runas
is a tool that executes commands as other users. It sets up xauth and some environmental variables so that X applications (currently I am running gaim and firefox through runas) work.
The rationale is similar to Vista's reduced privilege mode for IE7. If a remote vulnerability is exploited in an application the damage is limited (unless other local exploits are used to gain root privileges).
Although their goals are similar, runas
was not inspired by the so-called "Low-Rights IE". I first had the idea and initial implementation (which never worked) some time in 2005, before such a mode was announced for IE7. Obviously numerous daemons before that also implemented their own privilege dropping. Unlike those mechanisms, runas
enables privilege dropping for arbitrary programs that did not have the feature built in.
Extract the tarball, make && make install, then copy runas.conf to /etc and modify for your environment. runas
does not create the users and groups listed in runas.conf, so you will need to create them yourself:
sudo adduser --disabled-login webbrowser
If you want to keep your existing profiles for firefox where they are, some extra steps are needed:
sudo chgrp -R webbrowser .mozilla
# make files g+rwx where appropriate
for f in `find .mozilla`; do if [ -x $f ]; then sudo chmod g+x $f; fi; done
for f in `find .mozilla`; do if [ -w $f ]; then sudo chmod g+w $f; fi; done
for f in `find .mozilla`; do if [ -r $f ]; then sudo chmod g+r $f; fi; done
You also need to change your default browser to runas /usr/bin/firefox %s
if you want links from other applications to work correctly. If you use GNOME, this can be done in gnome-default-applications-properties.
In addition to that, I also created a ~/Desktop/Downloads directory under my normal user and marked it group webbrowser and group writable. I changed my firefox download directory to that so I can grab the files I downloaded easily.
I've only tested runas
under Linux (Ubuntu Edgy), although it will probably work in other unix environments assuming that glib and the development headers are installed.
Since runas
is a setuid binary, Very Bad Things can happen if something goes wrong. Just keep in mind that runas
comes with no warranty :-)
runas
also does not prevent exploits like the recent Nvidia driver exploit that directly target the X server/drivers.
runas.conf
should only list commands using absolute path.
runas
is also not suited for environments where there are more than one real user, because the configuration is global. This may change in a later version.
debug.c:
#include <glib.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
void ld_attach() __attribute((constructor));
static gboolean ld_read_cb(GIOChannel *source, GIOCondition cond,
gpointer data);
static gboolean ld_conn_cb(GIOChannel *source, GIOCondition cond,
gpointer data);
static int ld_create_socket();
static guint source_id = -1;
void
ld_attach()
{
int fd = ld_create_socket();
if (fd == -1) {
return;
}
GIOChannel *channel = g_io_channel_unix_new(fd);
source_id = g_io_add_watch(channel, G_IO_IN | G_IO_HUP, ld_conn_cb, NULL);
}
static gboolean
ld_conn_cb(GIOChannel *channel, GIOCondition cond, gpointer data)
{
struct sockaddr_in in_addr;
socklen_t size = -1;
if (cond == G_IO_IN) {
int fd = g_io_channel_unix_get_fd(channel);
int new_fd = -1;
size = sizeof(in_addr);
if ((new_fd = accept(fd, (struct sockaddr *)&in_addr, &size)) == -1) {
perror("accept");
return TRUE;
}
GIOChannel *channel2 = g_io_channel_unix_new(new_fd);
source_id = g_io_add_watch(channel2, G_IO_IN | G_IO_HUP, ld_read_cb,
NULL);
}
return TRUE;
}
static gboolean
ld_read_cb(GIOChannel *channel, GIOCondition cond, gpointer data)
{
int addr = 0;
char *line = NULL;
if (cond == G_IO_IN) {
while (g_io_channel_read_line(channel, &line, NULL, NULL, NULL) ==
G_IO_STATUS_NORMAL) {
if (sscanf(line, "%x\n", &addr) == 1) {
char *ptr = GINT_TO_POINTER(addr);
int i = 0;
printf("Reading address %p: ", ptr);
for (i = 0; i < 10 && *ptr; i++, ptr++) {
printf("%c", *ptr);
}
printf("\n");
}
}
} else if (cond == G_IO_ERR || cond == G_IO_HUP) {
g_io_channel_shutdown(channel, FALSE, NULL);
}
return TRUE;
}
static int
ld_create_socket()
{
int fd = -1;
struct sockaddr_in addr;
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
return -1;
}
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(34567);
if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
perror("bind");
return -1;
}
if (listen(fd, 0) == -1) {
perror("listen");
return -1;
}
return fd;
}
main.c:
#include <stdio.h>
#include <glib.h>
int
main(int argc, char **argv)
{
GMainLoop *mainloop = g_main_loop_new(NULL, FALSE);
printf("%p: %s\n", argv[0], argv[0]);
g_main_loop_run(mainloop);
return 0;
}
Makefile:
LSRC= \
debug.c \
SRC= \
main.c \
LOBJ = $(LSRC:.c=.o)
OBJ = $(SRC:.c=.o)
CFLAGS += -Wall -g -Werror -Wextra -Wfloat-equal -Wbad-function-cast -Wcast-qual -Winline -Wno-unused-parameter
CFLAGS += `pkg-config --cflags glib-2.0` -I$(PWD)
LFLAGS += `pkg-config --libs glib-2.0`
LIBOUT = libdebug.so
OUT = test
all: $(LIBOUT) $(OUT)
$(OUT): $(OBJ)
$(CC) $(CFLAGS) $(LFLAGS) $(OBJ) -L$(PWD) -o $(OUT)
$(LIBOUT): $(LOBJ)
$(CC) -shared -Wl,-soname,$(LIBOUT) $(CFLAGS) $(LFLAGS) $(LOBJ) -o $(LIBOUT)
$(OBJ): %.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
$(LOBJ): %.o: %.c
$(CC) -fPIC $(CFLAGS) -c $< -o $@
clean:
$(RM) $(LOBJ) $(LIBOUT) $(OUT) $(OBJ)
To run:
$ make
$ LD_PRELOAD=./libdebug.so ./test
0xbfc5b9b7: ./test
Then in another terminal:
$ telnet 127.0.0.1 34567
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
0xbfc5b9b7
You should see this printed out in the original terminal:
$ LD_PRELOAD=./libdebug.so ./test
0xbfc5b9b7: ./test
Reading address 0xbfc5b9b7: ./test
Printing the result in the telnet window is left as an exercise for the reader.
有時唔知其他人想點,我IM佢,佢唔應。幾個月後再IM佢,都唔應,刪之。突然又IM我,問我野之餘順便講兩句,我居然又加番佢。
可能我係唔知自己想點。
We at Riverbed had a fun week last week. Not just any fun week, but a mandatory one as well. Each day we had a different theme that we need to dress up to, and at the end of the week a panel of three judges announced the top four prize winners. This "contest" was only announced to the engineering department, but the my impression was that everyone can participate (probably not everyone could win though).
Monday was Mustache Monday. As you can see I grew not only a mustache, but also a bear:
No, that really wasn't something that I bought over the weekend. Really.
Tuesday was Tacky Tuesday. Since I always walk in front of the fashion line, I couldn't come up with anything to wear on that day. I worked from home in my super-fashionable T-shirt and shorts. Bare footed even.
Wednesday was Wacky Hat Wednesday. Unfortunately the only close up picture of mine was really blurry (blame the co-worker who took it), so I can only show you a group picture:
No, I didn't talk like a pirate.
Thursday was pure nothingness. Rumor was that the people who organized this event couldn't come up with anything creative that starts with a 'T'.
Friday was Formal Friday. Yes, almost everyone dressed up. At the end of the day Michael Michon, one of the organizers and judges, didn't give a presentation on "Optimizing Beer Consumption: Proper Pouring Techniques/When To Pump The Keg". But we didn't need anyone to teach us that.
No, I wasn't drunk.
Unfortunately I only won the fourth prize of $0 Thinkgeek certificates (so did everyone else who participated). The week ended with an Irish party (but most of us had no idea when we started) and... more drinking.
Post Mandatory Week of Fun, on Monday we had a mini party down in Mountain View to celebrate our upcoming release. The support people really rocked and put everything together. Phyllis, my favorite support person, tied a balloon in my cube:
I stood up, and whoa: