Jonathan Adams's Weblog

Thursday Jun 30, 2005

The FBT provider, opensolaris source, and fun with the environment

The FBT provider, opensolaris source, and fun with the environment

Now that opensolaris is out there, it's quite a bit easier for folks to use DTrace's FBT provider. FBT provides "function boundary tracing", i.e. it has probes for the entry and exit for almost every function in the kernel. This is amazingly powerful and flexible, but it leads to it being hard to use: with over 20,000 functions on a typical Solaris box, it's very hard to know where to start, especially without access to the source code.

With OpenSolaris, the source code is available. So to illustrate how you can use this newly available information to get something done, I thought I'd use a classic question: How can I examine and muck with the environment?

To start off, we need a plan of attack; since dtrace doesn't have any way of looping over datastructures, typically if you want to walk some datastructure, you just find a place where the kernel is already doing so, and use probes there to sneak a peak at the data as it goes by. The initial environment for a process is set up in the exec(2) system call, so lets see if we can find where we read in the data from the user process.

Looking at the source, exece() calls exec_common(), which is the main workhorse. There doesn't seem to be any direct mucking of the environment, but there is:

    222 	ua.fname = fname;
    223 	ua.argp = argp;
    224 	ua.envp = envp;
    225 
    226 	if ((error = gexec(&vp, &ua, &args, NULL, 0, &execsz,
    227 	    exec_file, p->p_cred)) != 0) {
Now we could continue to track all of this down, but it's much easier to just search usr/src/uts for references to the envp symbol. That leads us to stk_copyin(), the routine responsible for copying in everything which is needed on the stack. Here's the environment processing loop:
   1303 	if (envp != NULL) {
   1304 		for (;;) {
   1305 			if (stk_getptr(args, envp, &sp))
   1306 				return (EFAULT);
   1307 			if (sp == NULL)
   1308 				break;
   1309 			if ((error = stk_add(args, sp, UIO_USERSPACE)) != 0)
   1310 				return (error);
   1311 			envp += ptrsize;
   1312 		}
   1313 	}
Without even knowing what stk_getptr() and stk_add() do, we now have enough information to write a D script to get the environment of a process as it exec()s. Here's the basic outline:
  1. First, use fbt::stk_copyin:entry to stash a copy of the envp pointer.
  2. Second, use fbt::stk_getptr:entry to watch for reads from the stored envp address.
  3. Third, use fbt::stk_add:entry and fbt::stk_add:return to print out the environment.
  4. Lastly, use fbt::stk_copyin:return to clean up.
And here's our first script:
#!/usr/sbin/dtrace -s

#pragma D option quiet

fbt::stk_copyin:entry
{
	self->envp = (uintptr_t)args[0]->envp;
}

fbt::stk_getptr:entry
/ self->envp != 0 /
{
	/* check if we're looking at envp or envp+1 */
	self->on = ((arg1 - self->envp) <= sizeof (uint64_t));

	/* update envp if we're on */
	self->envp = self->on ? arg1 : self->envp;
}

fbt::stk_add:entry
/ self->on && args[2] == UIO_USERSPACE /
{
	self->ptr = arg1;
}

fbt::stk_add:return
/ self->ptr != 0 /
{
	printf("%.79s\n", copyinstr(self->ptr));
	self->ptr = 0;
	self->on = 0;
}

fbt::stk_copyin:return
{
	self->envp = 0;
	self->on = 0;
}
Note that we delay the copyinstr of stk_add()'s second argument until fbt::stk_add:return. This is due to the fact that dtrace(1M) cannot fault in pages; so if a probe tries to copyinstr an address which has not yet been touched, you'll get a runtime error like:
dtrace: error on enabled probe ID 4 (ID 12535: fbt:genunix:stk_add:entry):
invalid address (0x1818000) in action #1 at DIF offset 28
By waiting until the return probe, we avoid this problem; we know that the kernel just touched the page to read in its copy.

Now, looking at the environment is fun, but it would be even more interesting to change the environment of a process while it is being execed. This requires a bit more work, and access to the destructive action copyout(). I'm going to start with a script which requires a recent version of Solaris (snv_15+, or the OpenSolaris release), because Bryan introduced some nice string handling stuff recently. We'll adapt the script to S10 afterwards.

Lets start by saying we want to change the name of the environment variable "FOO" to "BAR", but leave the value the same. The basic idea is simple; copyin() the string in the fbt::stk_add:entry probe, and if it's the one we want to change, copyout() the changes. The kernel will then proceed to copyin() the changed string, and use it for the environment of the process. The complication is the same as before; what if the page hasn't yet been touched, or the copyout() operation fails (for example, if the string isn't writable)?

There's no simple solution, so I'm just going to check *afterwards* that we didn't miss changing it, and kill -9 the process if we did. It's vile, but effective. Here's the script:

#!/usr/sbin/dtrace -s

#pragma D option quiet
#pragma D option destructive

self uintptr_t ptr;

inline int interesting = (strtok(copyinstr(self->ptr), "=") == "FOO");

fbt::stk_copyin:entry
{
	self->envp = (uintptr_t)args[0]->envp;
}

fbt::stk_getptr:entry
/ self->envp != 0 /
{
	/* check if we're looking at envp or envp+1 */
	self->on = ((arg1 - self->envp) <= sizeof (uint64_t));

	/* update envp if we're on */
	self->envp = self->on ? arg1 : self->envp;
	self->ptr = 0;
}

fbt::stk_add:entry
/ self->on && args[2] == UIO_USERSPACE /
{
	self->ptr = arg1;
	self->didit = 0;
}

fbt::stk_add:entry
/ self->ptr != 0 && interesting /
{
	printf("%d: %s: changed env \"%s\"\n",
	    pid, execname, copyinstr(self->ptr));
	copyout("BAR", self->ptr, 3);		/* 3 == strlen("BAR") */
	self->didit = 1;
}

fbt::stk_add:return
/ self->ptr != 0 && interesting && !self->didit /
{
	printf("%d: %s: killed, env \"%s\" couldn't be changed\n",
	    pid, execname, copyinstr(self->ptr));
	raise(9);
}

fbt::stk_copyin:return
{
	self->envp = 0;
	self->on = 0;
	self->ptr = 0;
}
The above works great on Solaris Nevada and OpenSolaris, but doesn't work on Solaris 10, because it uses "strtok". So to use it on Solaris 10, we'll have to do things slightly more manually. The only thing that needs to change is the definition of the "interesting" inline, and some more cleanup in fbt::stk_copyin:return:
inline int interesting =
    ((self->str = copyinstr(self->ptr), "=")[0] == 'F' &&
    self->str[1] == 'O' &&
    self->str[2] == 'O' &&
    self->str[3] == '=');
...
fbt::stk_copyin:return
{
	self->envp = 0;
	self->on = 0;
	self->ptr = 0;
	self->str = 0;
}
A final note is on stability; we're using private implementation details of Solaris to make this all work, and they are subject to change without notice at any time. This particular part of solaris isn't likely to change much, but you never know. A reasonable RFE would be for more Stable probe-points in the exec(3C) family, so that people can write things like this more stably.

Technorati Tag:
Technorati Tag:
Technorati Tag:

Comments:

Folks from the DTrace discussion forum adapted the above to the recent <tt>LD_AUDIT</tt> security hole; I've made my own version, which is robust and low-overhead:
#!/usr/sbin/dtrace -s

#pragma D option quiet
#pragma D option destructive

inline unsigned int SUGID = 0x00002000;
inline unsigned int SNOCD = 0x10000000;
inline unsigned int PSUIDFLAGS = SUGID|SNOCD;

self char *str;

/* catches more than LD_AUDIT{,_32,_64}, but who cares? */
inline int interesting = (self->str[8] = 0) == 0 &&
    (stringof(self->str) == "LD_AUDIT");

proc:::exec
{
	self->execname = args[0];
}

fbt::stk_add:entry
/ args[2] == UIO_USERSPACE /
{
	self->ptr = arg1;
}

fbt::stk_add:return
/ self->ptr != 0 &&
  (self->str = copyinstr(self->ptr)) != NULL && interesting /
{
	self->interesting = 1;
	self->report = copyinstr(self->ptr);
}

proc:::exec-success
/ self->interesting && (curthread->t_procp->p_flag & PSUIDFLAGS) /
{
	system(
	    "logger -pauth.crit \"%d: %s execing setuid %s w/ '%s', killed\"",
	    pid, execname, self->execname, self->report);
	raise(9);
}

proc:::exec-success, proc:::exec-failure
{
	self->ptr = 0;
	self->str = 0;
	self->interesting = 0;
	self->execname = 0;
	self->report = 0;
}
It logs to syslog every time it kills something.

Posted by Jonathan Adams on July 01, 2005 at 12:57 AM PDT #

对不起我的最爱 暧昧 冬天快乐 披着羊皮的狼 桃花朵朵开 神话 笔记 吉祥三宝 发如雪 爸爸妈妈 我很想爱他 夜曲 千里之外 不得不爱 王子变青蛙 冰菊舞 飞舞 爱我别走 听妈妈的话 只剩我一个 我不后悔 飞行部落 反转地球 死了都要爱 好姑娘 一万个理由 曹操 qq爱 认真的雪 舞娘 老婆老婆我爱你 约定 大城小爱 号码 老公老公我爱你 天下无双 狼爱上羊 寻找李慧珍 不要再来伤害我 不怕不怕 香飘飘 我们都是好孩子 求佛 秋天不回来 香水有毒 皇后与梦想 每一面都美太美丽 那一夜 真爱 隐形的翅膀 对不起我的最爱 暧昧 冬天快乐 披着羊皮的狼 桃花朵朵开 神话 笔记 吉祥三宝 发如雪 爸爸妈妈 我很想爱他 夜曲 千里之外 不得不爱 王子变青蛙 冰菊舞 飞舞 爱我别走 听妈妈的话 只剩我一个 我不后悔 飞行部落 反转地球 死了都要爱 好姑娘 一万个理由 曹操 qq爱 认真的雪 舞娘 老婆老婆我爱你 约定 大城小爱 号码 老公老公我爱你 天下无双 狼爱上羊 寻找李慧珍 不要再来伤害我 不怕不怕 香飘飘 我们都是好孩子 求佛 秋天不回来 香水有毒 皇后与梦想 每一面都美太美丽 那一夜 真爱 隐形的翅膀 对不起我的最爱 暧昧 冬天快乐 披着羊皮的狼 桃花朵朵开 神话 笔记 吉祥三宝 发如雪 爸爸妈妈 我很想爱他 夜曲 千里之外 不得不爱 王子变青蛙 冰菊舞 飞舞 爱我别走 听妈妈的话 只剩我一个 我不后悔 飞行部落 反转地球 死了都要爱 好姑娘 一万个理由 曹操 qq爱 认真的雪 舞娘 老婆老婆我爱你 约定 大城小爱 号码 老公老公我爱你 天下无双 狼爱上羊 寻找李慧珍 不要再来伤害我 不怕不怕 香飘飘 我们都是好孩子 求佛 秋天不回来 香水有毒 皇后与梦想 每一面都美太美丽 那一夜 真爱 隐形的翅膀 对不起我的最爱 暧昧 冬天快乐 披着羊皮的狼 桃花朵朵开 神话 笔记 吉祥三宝 发如雪 爸爸妈妈 我很想爱他 夜曲 千里之外 不得不爱 王子变青蛙 冰菊舞 飞舞 爱我别走 听妈妈的话 只剩我一个 我不后悔 飞行部落 反转地球 死了都要爱 好姑娘 一万个理由 曹操 qq爱 认真的雪 舞娘 老婆老婆我爱你 约定 大城小爱 号码 老公老公我爱你 天下无双 狼爱上羊 寻找李慧珍 不要再来伤害我 不怕不怕 香飘飘 我们都是好孩子 求佛 秋天不回来 香水有毒 皇后与梦想 每一面都美太美丽 那一夜 真爱 隐形的翅膀 对不起我的最爱 暧昧 冬天快乐 披着羊皮的狼 桃花朵朵开 神话 笔记 吉祥三宝 发如雪 爸爸妈妈 我很想爱他 夜曲 千里之外 不得不爱 王子变青蛙 冰菊舞 飞舞 爱我别走 听妈妈的话 只剩我一个 我不后悔 飞行部落 反转地球 死了都要爱 好姑娘 一万个理由 曹操 qq爱 认真的雪 舞娘 老婆老婆我爱你 约定 大城小爱 号码 老公老公我爱你 天下无双 狼爱上羊 寻找李慧珍 不要再来伤害我 不怕不怕 香飘飘 我们都是好孩子 求佛 秋天不回来 香水有毒 皇后与梦想 每一面都美太美丽 那一夜 真爱 隐形的翅膀 对不起我的最爱 暧昧 冬天快乐 披着羊皮的狼 桃花朵朵开 神话 笔记 吉祥三宝 发如雪 爸爸妈妈 我很想爱他 夜曲 千里之外 不得不爱 王子变青蛙 冰菊舞 飞舞 爱我别走 听妈妈的话 只剩我一个 我不后悔 飞行部落 反转地球 死了都要爱 好姑娘 一万个理由 曹操 qq爱 认真的雪 舞娘 老婆老婆我爱你 约定 大城小爱 号码 老公老公我爱你 天下无双 狼爱上羊 寻找李慧珍 不要再来伤害我 不怕不怕 香飘飘 我们都是好孩子 求佛 秋天不回来 香水有毒 皇后与梦想 每一面都美太美丽 那一夜 真爱 隐形的翅膀 韩国色情片 制服诱惑 欧美无码 性爱卡通影片 欧美激情 性爱卡通 免费激情电影 激情黄色电影 免费黄色电影 色情小说 黄色论坛 一夜情 黄色聊天室 乱伦 明星走光图片 肛交 美女视频 成人聊天室 网友自拍 黄色录象 少妇自拍 成人小电影 日本av女优 口交 美女图片 黄色 偷拍 性交 色情聊天室 走光图片 性爱电影 成人文学 色情小说 性爱贴图 成人漫画 成人书库 色情漫画 免费激情电影 成人游戏 黄色电影 艳情小说 激情小电影 黄色图片 色情图片 性生活 成人图片 成人色情 成人贴图 色情电影 激情图片 黄色小说 成人电影 激情电影 色情网站 激情女郎 劲舞团 三级片 性爱图片 跑跑卡丁车 激情正点自拍 黄色网站 美女走光 免费黄色电影 诱惑自拍下载 色情文学 情色电影 裸体图片 裸体美女视频自拍 免费电影 成人小说 成人论坛 成人网站 pp点点通 色情论坛 免费三级片 激情视频自拍 免费成人电影 韩国色情片 制服诱惑 欧美无码 性爱卡通影片 欧美激情 性爱卡通 免费激情电影 激情黄色电影 免费黄色电影 色情小说 黄色论坛 一夜情 黄色聊天室 乱伦 明星走光图片 肛交 美女视频 成人聊天室 网友自拍 黄色录象 少妇自拍 成人小电影 日本av女优 口交 美女图片 黄色 偷拍 性交 色情聊天室 走光图片 性爱电影 成人文学 色情小说 性爱贴图 成人漫画 成人书库 色情漫画 免费激情电影 成人游戏 黄色电影 艳情小说 激情小电影 黄色图片 色情图片 性生活 成人图片 成人色情 成人贴图 色情电影 激情图片 黄色小说 成人电影 激情电影 色情网站 激情女郎 劲舞团 三级片 性爱图片 跑跑卡丁车 激情正点自拍 黄色网站 美女走光 免费黄色电影 诱惑自拍下载 色情文学 情色电影 裸体图片 裸体美女视频自拍 免费电影 成人小说 成人论坛 成人网站 pp点点通 色情论坛 免费三级片 激情视频自拍 免费成人电影 韩国色情片 制服诱惑 欧美无码 性爱卡通影片 欧美激情 性爱卡通 免费激情电影 激情黄色电影 免费黄色电影 色情小说 黄色论坛 一夜情 黄色聊天室 乱伦 明星走光图片 肛交 美女视频 成人聊天室 网友自拍 黄色录象 少妇自拍 成人小电影 日本av女优 口交 美女图片 黄色 偷拍 性交 色情聊天室 走光图片 性爱电影 成人文学 色情小说 性爱贴图 成人漫画 成人书库 色情漫画 免费激情电影 成人游戏 黄色电影 艳情小说 激情小电影 黄色图片 色情图片 性生活 成人图片 成人色情 成人贴图 色情电影 激情图片 黄色小说 成人电影 激情电影 色情网站 激情女郎 劲舞团 三级片 性爱图片 跑跑卡丁车 激情正点自拍 黄色网站 美女走光 韩国色情片 制服诱惑 欧美无码 性爱卡通影片 欧美激情 性爱卡通 免费激情电影 激情黄色电影 免费黄色电影 色情小说 黄色论坛 免费黄色电影 诱惑自拍下载 色情文学 情色电影 裸体图片 裸体美女视频自拍 免费电影 成人小说 成人论坛 成人网站 pp点点通 色情论坛 免费三级片 激情视频自拍 免费成人电影 韩国色情片 制服诱惑 欧美无码 性爱卡通影片 欧美激情 性爱卡通 免费激情电影 激情黄色电影 免费黄色电影 色情小说 黄色论坛 一夜情 黄色聊天室 乱伦 明星走光图片 肛交 美女视频 成人聊天室 网友自拍 黄色录象 少妇自拍 成人小电影 日本av女优 口交 七夕情人站 360家具家居网 剧情网 育崽妈咪网 泡泡写真图库 狐谷娱乐 狐谷小游戏 上网就要去 美女图片 黄色 偷拍 性交 色情聊天室 走光图片 性爱电影 黄色小说 裸体美女 韩国三级片 免费黄色电影下载 黄色小电影下载 激情免费电影 激情电影免费 免费成人电影 成人文学 色情小说 性爱贴图 成人漫画 成人书库 色情漫画 免费激情电影 成人游戏 黄色电影 艳情小说 激情小电影 黄色图片 色情图片 性生活 成人图片 成人色情 成人贴图 色情电影 激情图片 黄色小说 成人电影 激情电影 色情网站 激情女郎 劲舞团 三级片 性爱图片 跑跑卡丁车 激情正点自拍 黄色网站 美女走光 免费黄色电影 诱惑自拍下载 色情文学 情色电影 裸体图片 裸体美女视频自拍 免费电影 成人小说 成人论坛 成人网站 pp点点通 色情论坛 免费三级片 激情视频自拍 免费成人电影 韩国色情片 制服诱惑 欧美无码 性爱卡通影片 欧美激情 性爱卡通 免费激情电影 激情黄色电影 免费黄色电影 色情小说 黄色论坛 一夜情 黄色聊天室 乱伦 明星走光图片 肛交 美女视频 成人聊天室 网友自拍 黄色录象 少妇自拍 成人小电影 日本av女优 口交 美女图片 黄色 偷拍 性交 色情聊天室 走光图片 性爱电影 成人文学 色情小说 性爱贴图 成人漫画 成人书库 色情漫画 免费激情电影 成人游戏 黄色电影 艳情小说 激情小电影 黄色图片 色情图片 性生活 成人图片 成人色情 成人贴图 色情电影 激情图片 黄色小说 成人电影 激情电影 色情网站 激情女郎 劲舞团 三级片 性爱图片 跑跑卡丁车 激情正点自拍 黄色网站 美女走光 免费黄色电影 诱惑自拍下载 色情文学 情色电影 裸体图片 裸体美女视频自拍 免费电影 成人小说 成人论坛 成人网站 pp点点通 色情论坛 免费三级片 激情视频自拍 免费成人电影 偷拍桌球室里的丰满少妇 乳沟深深 意外偷拍到的镜头 酒吧美女脱衣舞秀丁字裤 抓拍沙滩上没穿胸罩的MM 丝袜诱惑 波霸美少女视频 脱衣舞-夜总会艳舞07 色情男人看A片玩激情 宿舍里玩弄巨乳女学生 奴隶情人 女秘书办公室妩媚自拍 视频主持MM自拍性感热舞 诱人的脱衣舞表演 激情男女QQ视频热舞 美女与野兽 韩国三级明星写真 视频聊天室的风骚女室主 法国透明内衣秀 欧美性感AV女郎火辣自拍 一个聊天室MM的性感热舞 超性感AV女优室内激情 抓拍漂亮MM蹦床超级走光 美女记者前故意撕衫走光 全裸喂奶的真实镜头 性感少妇跳风骚脱衣舞 脱衣舞-夜总会艳舞06 网友自拍室友房内激情事 两洋妞超下流激情自拍 红衣爆乳妹浪情写真 石屋女子唤醒野性欲望 免费点歌 手机视频 手机彩图 热门铃声 劲爆DJ 求佛 秋天不回来 月亮之上 qq爱 不怕不怕 香水有毒 千里之外 大城小爱 老婆老婆我爱你 听妈妈的话 今天你要嫁给我 那一夜 狼爱上羊 隐形的翅膀 认真的雪 寂寞沙洲冷 一万个理由 不要再来伤害我 期待 飞舞 夜曲 爸爸妈妈 我不后悔 本草纲目 笔记 触电 号码 爱我别走 太美丽 127日 反转地球 对不起我的最爱 曹操 死了都要爱 真爱 不得不爱 玩美 香飘飘 美丽心情 吻别 花的嫁纱 莫斯科没有眼泪 千年之恋 爱如潮水 哎呀 发如雪 化蝶飞 蓝眼泪 飘雪 你的眼神 天下无双 婴儿 樱花草 七天七世纪 今夜你会不会来 大城小事 你怎么舍得我难过 十元人民币 天亮了 千千阙歌 借口 分手快乐 寓言 偏偏喜欢你 香水百合 两只小蜜蜂 上海滩 桃花朵朵开 遗失的美好 我们能不能不分手 爱上你我很快乐 一路上有你 快乐练习曲 天涯 高手 恋曲1990 江湖笑 大约在冬季 情画 爱我就别伤害我 放飞美丽 喜欢你 女人花 一生爱你千百回 你的样子 春泥 昨日重现 谢谢你的爱 一千零一夜 心雨 月亮惹的祸 说爱你 分飞 回头太难 哑巴新娘 曾经最美 西厢 希望 别怕我伤心 我只在乎你 你到底爱谁 爱很简单 当你孤单你会想起谁 心肝宝贝 一直很安静 光辉岁月 盖世英雄 冰菊舞 吉祥三宝 祝你一路顺风 欧若拉 水手 解脱 丝路 我说我爱你 安静 燕尾蝶 月光 一千个伤心的理由 一个人哭 爱情木瓜 我要的世界 无间道 梁祝 眉飞色舞 雨人 感恩的心 轨迹 红模仿 红色石头 折子戏 挪威的森林 戒不掉 童年 美丽的神话 猪都笑了 快乐崇拜 give me five 别说我的眼泪你无所谓 广岛之恋 我的果汁分你一半 让泪化作相思雨 精忠报国 双鱼座 秋天的童话 在他乡 虫儿飞 过火 我们都是好孩子 爱情 双截棍 完美世界 嘻唰唰 黑色幽默 假装 蜗牛 潘朵拉 爱如空气 容易受伤的女人 手放开 见习爱神 一剪梅 你的微笑 我不想说我是鸡 童话 无尽的爱 蓝莲花 我爱你你却爱着他 恋着多喜欢 大舌头 我要抱着你 绝口不提爱你 走出喜马拉雅 披着羊皮的狼 铁血丹心 从开始到现在 我不愿看见你再流泪 爱笑的眼睛 明天会更好 受了点伤 如果没有你 记事本 大地 都是你 如果爱 天空 说爱我 小薇 曾经的你 倒带 不痛 痛快 断了的弦 晴天 星光游乐园 真爱你的云 <a href="http://www.popyy.cn/music/

Posted by fdasfdsa on October 12, 2006 at 06:50 AM PDT #

Post a Comment:
  • HTML Syntax: NOT allowed

Calendar

Feeds

Search

Navigation

Referrers