Commit 7404d0e8 authored by Brendan Gregg's avatar Brendan Gregg Committed by GitHub

Merge pull request #95 from iovisor/username

add username builtin
parents d0ba7cd8 83a9e292
...@@ -54,10 +54,10 @@ void CodegenLLVM::visit(Builtin &builtin) ...@@ -54,10 +54,10 @@ void CodegenLLVM::visit(Builtin &builtin)
expr_ = b_.CreateAnd(pidtgid, 0xffffffff); expr_ = b_.CreateAnd(pidtgid, 0xffffffff);
} }
} }
else if (builtin.ident == "uid" || builtin.ident == "gid") else if (builtin.ident == "uid" || builtin.ident == "gid" || builtin.ident == "username")
{ {
Value *uidgid = b_.CreateGetUidGid(); Value *uidgid = b_.CreateGetUidGid();
if (builtin.ident == "uid") if (builtin.ident == "uid" || builtin.ident == "username")
{ {
expr_ = b_.CreateAnd(uidgid, 0xffffffff); expr_ = b_.CreateAnd(uidgid, 0xffffffff);
} }
......
...@@ -76,6 +76,9 @@ void SemanticAnalyser::visit(Builtin &builtin) ...@@ -76,6 +76,9 @@ void SemanticAnalyser::visit(Builtin &builtin)
builtin.type = SizedType(Type::name, 8); builtin.type = SizedType(Type::name, 8);
probe_->need_expansion = true; probe_->need_expansion = true;
} }
else if (builtin.ident == "username") {
builtin.type = SizedType(Type::username, 8);
}
else { else {
builtin.type = SizedType(Type::none, 0); builtin.type = SizedType(Type::none, 0);
err_ << "Unknown builtin variable: '" << builtin.ident << "'" << std::endl; err_ << "Unknown builtin variable: '" << builtin.ident << "'" << std::endl;
......
...@@ -212,6 +212,8 @@ void perf_event_printer(void *cb_cookie, void *data, int size) ...@@ -212,6 +212,8 @@ void perf_event_printer(void *cb_cookie, void *data, int size)
auto args = std::get<1>(bpftrace->printf_args_[printf_id]); auto args = std::get<1>(bpftrace->printf_args_[printf_id]);
std::vector<uint64_t> arg_values; std::vector<uint64_t> arg_values;
std::vector<std::unique_ptr<char>> resolved_symbols; std::vector<std::unique_ptr<char>> resolved_symbols;
std::vector<std::unique_ptr<char>> resolved_usernames;
char *name; char *name;
for (auto arg : args) for (auto arg : args)
{ {
...@@ -249,6 +251,11 @@ void perf_event_printer(void *cb_cookie, void *data, int size) ...@@ -249,6 +251,11 @@ void perf_event_printer(void *cb_cookie, void *data, int size)
bpftrace->resolve_usym(*(uint64_t*)(arg_data+arg.offset), *(uint64_t*)(arg_data+arg.offset + 8)).c_str())); bpftrace->resolve_usym(*(uint64_t*)(arg_data+arg.offset), *(uint64_t*)(arg_data+arg.offset + 8)).c_str()));
arg_values.push_back((uint64_t)resolved_symbols.back().get()); arg_values.push_back((uint64_t)resolved_symbols.back().get());
break; break;
case Type::username:
resolved_usernames.emplace_back(strdup(
bpftrace->resolve_uid(*(uint64_t*)(arg_data+arg.offset)).c_str()));
arg_values.push_back((uint64_t)resolved_usernames.back().get());
break;
case Type::name: case Type::name:
name = strdup(bpftrace->resolve_name(*(uint64_t*)(arg_data+arg.offset)).c_str()); name = strdup(bpftrace->resolve_name(*(uint64_t*)(arg_data+arg.offset)).c_str());
arg_values.push_back((uint64_t)name); arg_values.push_back((uint64_t)name);
...@@ -660,6 +667,8 @@ int BPFtrace::print_map(IMap &map, uint32_t top, uint32_t div) ...@@ -660,6 +667,8 @@ int BPFtrace::print_map(IMap &map, uint32_t top, uint32_t div)
std::cout << resolve_sym(*(uintptr_t*)value.data()); std::cout << resolve_sym(*(uintptr_t*)value.data());
else if (map.type_.type == Type::usym) else if (map.type_.type == Type::usym)
std::cout << resolve_usym(*(uintptr_t*)value.data(), *(uint64_t*)(value.data() + 8)); std::cout << resolve_usym(*(uintptr_t*)value.data(), *(uint64_t*)(value.data() + 8));
else if (map.type_.type == Type::username)
std::cout << resolve_uid(*(uint64_t*)(value.data())) << std::endl;
else if (map.type_.type == Type::string) else if (map.type_.type == Type::string)
std::cout << value.data() << std::endl; std::cout << value.data() << std::endl;
else if (map.type_.type == Type::count || map.type_.type == Type::sum) else if (map.type_.type == Type::count || map.type_.type == Type::sum)
...@@ -1107,6 +1116,49 @@ std::string BPFtrace::get_stack(uint64_t stackidpid, bool ustack, int indent) ...@@ -1107,6 +1116,49 @@ std::string BPFtrace::get_stack(uint64_t stackidpid, bool ustack, int indent)
return stack.str(); return stack.str();
} }
std::string BPFtrace::resolve_uid(uintptr_t addr)
{
std::string file_name = "/etc/passwd";
std::string uid = std::to_string(addr);
std::string username = "";
std::ifstream file(file_name);
if (file.fail())
{
std::cerr << strerror(errno) << ": " << file_name << std::endl;
return username;
}
std::string line;
bool found = false;
while (std::getline(file, line) && !found)
{
auto fields = split_string(line, ':');
if (fields[2] == uid)
{
found = true;
username = fields[0];
}
}
file.close();
return username;
}
std::vector<std::string> BPFtrace::split_string(std::string &str, char split_by)
{
std::vector<std::string> elems;
std::stringstream ss(str);
std::string value;
while(std::getline(ss, value, split_by)) {
elems.push_back(value);
}
return elems;
}
std::string BPFtrace::resolve_sym(uintptr_t addr, bool show_offset) std::string BPFtrace::resolve_sym(uintptr_t addr, bool show_offset)
{ {
struct bcc_symbol sym; struct bcc_symbol sym;
......
...@@ -37,6 +37,7 @@ public: ...@@ -37,6 +37,7 @@ public:
std::string get_stack(uint64_t stackidpid, bool ustack, int indent=0); std::string get_stack(uint64_t stackidpid, bool ustack, int indent=0);
std::string resolve_sym(uintptr_t addr, bool show_offset=false); std::string resolve_sym(uintptr_t addr, bool show_offset=false);
std::string resolve_usym(uintptr_t addr, int pid, bool show_offset=false); std::string resolve_usym(uintptr_t addr, int pid, bool show_offset=false);
std::string resolve_uid(uintptr_t addr);
uint64_t resolve_kname(const char *name); uint64_t resolve_kname(const char *name);
uint64_t resolve_uname(const char *name, const char *path); uint64_t resolve_uname(const char *name, const char *path);
std::string resolve_name(uint64_t name_id); std::string resolve_name(uint64_t name_id);
...@@ -87,6 +88,7 @@ private: ...@@ -87,6 +88,7 @@ private:
static std::string exec_system(const char* cmd); static std::string exec_system(const char* cmd);
static std::string hist_index_label(int power); static std::string hist_index_label(int power);
static std::string lhist_index_label(int number); static std::string lhist_index_label(int number);
static std::vector<std::string> split_string(std::string &str, char split_by);
std::vector<uint8_t> find_empty_key(IMap &map, size_t size) const; std::vector<uint8_t> find_empty_key(IMap &map, size_t size) const;
}; };
......
...@@ -48,7 +48,7 @@ path :(\\.|[_\-\./a-zA-Z0-9])*: ...@@ -48,7 +48,7 @@ path :(\\.|[_\-\./a-zA-Z0-9])*:
<COMMENT>"*/" BEGIN(INITIAL); <COMMENT>"*/" BEGIN(INITIAL);
<COMMENT>"EOF" driver.error(loc, std::string("end of file during comment")); <COMMENT>"EOF" driver.error(loc, std::string("end of file during comment"));
pid|tid|uid|gid|nsecs|cpu|comm|stack|ustack|arg[0-9]|retval|func|name|curtask|rand|ctx { pid|tid|uid|gid|nsecs|cpu|comm|stack|ustack|arg[0-9]|retval|func|name|curtask|rand|ctx|username {
return Parser::make_BUILTIN(yytext, loc); } return Parser::make_BUILTIN(yytext, loc); }
{path} { return Parser::make_PATH(yytext, loc); } {path} { return Parser::make_PATH(yytext, loc); }
{map} { return Parser::make_MAP(yytext, loc); } {map} { return Parser::make_MAP(yytext, loc); }
......
...@@ -74,6 +74,8 @@ std::string MapKey::argument_value(BPFtrace &bpftrace, ...@@ -74,6 +74,8 @@ std::string MapKey::argument_value(BPFtrace &bpftrace,
return bpftrace.resolve_sym(*(uint64_t*)data); return bpftrace.resolve_sym(*(uint64_t*)data);
case Type::usym: case Type::usym:
return bpftrace.resolve_usym(*(uint64_t*)data, *(uint64_t*)(arg_data + 8)); return bpftrace.resolve_usym(*(uint64_t*)data, *(uint64_t*)(arg_data + 8));
case Type::username:
return bpftrace.resolve_uid(*(uint64_t*)data);
case Type::name: case Type::name:
return bpftrace.name_ids_[*(uint64_t*)data]; return bpftrace.name_ids_[*(uint64_t*)data];
case Type::string: case Type::string:
......
...@@ -33,7 +33,7 @@ std::string verify_format_string(const std::string &fmt, std::vector<Field> args ...@@ -33,7 +33,7 @@ std::string verify_format_string(const std::string &fmt, std::vector<Field> args
for (int i=0; i<num_args; i++, token_iter++) for (int i=0; i<num_args; i++, token_iter++)
{ {
Type arg_type = args.at(i).type.type; Type arg_type = args.at(i).type.type;
if (arg_type == Type::sym || arg_type == Type::usym || arg_type == Type::name) if (arg_type == Type::sym || arg_type == Type::usym || arg_type == Type::name || arg_type == Type::username)
arg_type = Type::string; // Symbols should be printed as strings arg_type = Type::string; // Symbols should be printed as strings
int offset = 1; int offset = 1;
......
...@@ -32,6 +32,7 @@ enum class Type ...@@ -32,6 +32,7 @@ enum class Type
cast, cast,
join, join,
name, name,
username,
}; };
std::ostream &operator<<(std::ostream &os, Type type); std::ostream &operator<<(std::ostream &os, Type type);
......
...@@ -1024,6 +1024,57 @@ attributes #1 = { argmemonly nounwind } ...@@ -1024,6 +1024,57 @@ attributes #1 = { argmemonly nounwind }
)EXPECTED"); )EXPECTED");
} }
TEST(codegen, builtin_username)
{
test("kprobe:f { @x = username; @y = gid}",
R"EXPECTED(; Function Attrs: nounwind
declare i64 @llvm.bpf.pseudo(i64, i64) #0
; Function Attrs: argmemonly nounwind
declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) #1
define i64 @"kprobe:f"(i8* nocapture readnone) local_unnamed_addr section "s_kprobe:f" {
entry:
%"@y_val" = alloca i64, align 8
%"@y_key" = alloca i64, align 8
%"@x_val" = alloca i64, align 8
%"@x_key" = alloca i64, align 8
%get_uid_gid = tail call i64 inttoptr (i64 15 to i64 ()*)()
%1 = and i64 %get_uid_gid, 4294967295
%2 = bitcast i64* %"@x_key" to i8*
call void @llvm.lifetime.start.p0i8(i64 -1, i8* nonnull %2)
store i64 0, i64* %"@x_key", align 8
%3 = bitcast i64* %"@x_val" to i8*
call void @llvm.lifetime.start.p0i8(i64 -1, i8* nonnull %3)
store i64 %1, i64* %"@x_val", align 8
%pseudo = tail call i64 @llvm.bpf.pseudo(i64 1, i64 1)
%update_elem = call i64 inttoptr (i64 2 to i64 (i8*, i8*, i8*, i64)*)(i64 %pseudo, i64* nonnull %"@x_key", i64* nonnull %"@x_val", i64 0)
call void @llvm.lifetime.end.p0i8(i64 -1, i8* nonnull %2)
call void @llvm.lifetime.end.p0i8(i64 -1, i8* nonnull %3)
%get_uid_gid1 = call i64 inttoptr (i64 15 to i64 ()*)()
%4 = lshr i64 %get_uid_gid1, 32
%5 = bitcast i64* %"@y_key" to i8*
call void @llvm.lifetime.start.p0i8(i64 -1, i8* nonnull %5)
store i64 0, i64* %"@y_key", align 8
%6 = bitcast i64* %"@y_val" to i8*
call void @llvm.lifetime.start.p0i8(i64 -1, i8* nonnull %6)
store i64 %4, i64* %"@y_val", align 8
%pseudo2 = call i64 @llvm.bpf.pseudo(i64 1, i64 2)
%update_elem3 = call i64 inttoptr (i64 2 to i64 (i8*, i8*, i8*, i64)*)(i64 %pseudo2, i64* nonnull %"@y_key", i64* nonnull %"@y_val", i64 0)
call void @llvm.lifetime.end.p0i8(i64 -1, i8* nonnull %5)
call void @llvm.lifetime.end.p0i8(i64 -1, i8* nonnull %6)
ret i64 0
}
; Function Attrs: argmemonly nounwind
declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) #1
attributes #0 = { nounwind }
attributes #1 = { argmemonly nounwind }
)EXPECTED");
}
TEST(codegen, call_kaddr) TEST(codegen, call_kaddr)
{ {
// TODO: test kaddr() // TODO: test kaddr()
......
...@@ -26,6 +26,7 @@ TEST(Parser, builtin_variables) ...@@ -26,6 +26,7 @@ TEST(Parser, builtin_variables)
test("kprobe:f { pid }", "Program\n kprobe:f\n builtin: pid\n"); test("kprobe:f { pid }", "Program\n kprobe:f\n builtin: pid\n");
test("kprobe:f { tid }", "Program\n kprobe:f\n builtin: tid\n"); test("kprobe:f { tid }", "Program\n kprobe:f\n builtin: tid\n");
test("kprobe:f { uid }", "Program\n kprobe:f\n builtin: uid\n"); test("kprobe:f { uid }", "Program\n kprobe:f\n builtin: uid\n");
test("kprobe:f { username }", "Program\n kprobe:f\n builtin: username\n");
test("kprobe:f { gid }", "Program\n kprobe:f\n builtin: gid\n"); test("kprobe:f { gid }", "Program\n kprobe:f\n builtin: gid\n");
test("kprobe:f { nsecs }", "Program\n kprobe:f\n builtin: nsecs\n"); test("kprobe:f { nsecs }", "Program\n kprobe:f\n builtin: nsecs\n");
test("kprobe:f { cpu }", "Program\n kprobe:f\n builtin: cpu\n"); test("kprobe:f { cpu }", "Program\n kprobe:f\n builtin: cpu\n");
......
...@@ -54,6 +54,7 @@ TEST(semantic_analyser, builtin_variables) ...@@ -54,6 +54,7 @@ TEST(semantic_analyser, builtin_variables)
test("kprobe:f { pid }", 0); test("kprobe:f { pid }", 0);
test("kprobe:f { tid }", 0); test("kprobe:f { tid }", 0);
test("kprobe:f { uid }", 0); test("kprobe:f { uid }", 0);
test("kprobe:f { username }", 0);
test("kprobe:f { gid }", 0); test("kprobe:f { gid }", 0);
test("kprobe:f { nsecs }", 0); test("kprobe:f { nsecs }", 0);
test("kprobe:f { cpu }", 0); test("kprobe:f { cpu }", 0);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment