From: Kim Gunsoo Date: Wed, 6 Jan 2016 08:29:02 +0000 (+0900) Subject: Merge branch 'tizen_2.4_merge' into tizen X-Git-Tag: submit/tizen/20160128.073515~1 X-Git-Url: http://review.tizen.org/git/?p=sdk%2Ftarget%2Fsdbd.git;a=commitdiff_plain;h=ba75c7d23440fb026ca1c3c036c327a7fd22e1ba Merge branch 'tizen_2.4_merge' into tizen Change-Id: Iff477f5ca164496b2ab6144f35195ffeb7dbcbdc Signed-off-by: Kim Gunsoo --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 95e9b08..f160f95 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,7 +19,14 @@ project (sdbd) option(USE_FUNCTION_FS "Use FunctionFS" NO) option(BUILD_UNIT_TESTS "Build unit tests" NO) -set(sdbd_SRCS + +############################# cmake packages ################################## + +INCLUDE(FindPkgConfig) + +############################# compiler flags ################################## + +SET(SDBD_SRCS src/sdb.c src/fdevent.c src/transport.c @@ -28,6 +35,7 @@ set(sdbd_SRCS src/sockets.c src/services.c src/file_sync_service.c + src/usb_linux_client.c src/utils.c src/socket_inaddr_any_server.c src/socket_local_client.c @@ -45,9 +53,51 @@ set(sdbd_SRCS src/usb_funcfs_client.c ) -include_directories(src) +include(FindPkgConfig) + +pkg_check_modules(pkgs REQUIRED + libtzplatform-config + capi-system-info + vconf + glib-2.0 + dbus-1 + dbus-glib-1 + ) + +FOREACH(flag ${pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") + +INCLUDE_DIRECTORIES(src) + +ADD_DEFINITIONS("-O2 -g -Wall -Wno-unused-parameter -fPIE") +ADD_DEFINITIONS("-DSDB_HOST=0") +ADD_DEFINITIONS("-D_XOPEN_SOURCE") +ADD_DEFINITIONS("-D_GNU_SOURCE") +ADD_DEFINITIONS("-DHAVE_FORKEXEC") +ADD_DEFINITIONS("-D_DROP_PRIVILEGE") +ADD_DEFINITIONS("-D_FILE_OFFSET_BITS=64") + +IF (_ARM_TARGET) + ADD_DEFINITIONS("-DANDROID_GADGET=1") +ENDIF (_ARM_TARGET) + +IF(TARGET_ARCH STREQUAL x86) + ADD_DEFINITIONS("-DTARGET_ARCH_X86") +ELSE() + ADD_DEFINITIONS("-DTARGET_ARCH_ARM") +ENDIF() + +IF(WEARABLE_PROFILE STREQUAL on) + ADD_DEFINITIONS("-D_WEARABLE") +ENDIF() + +find_package(Threads REQUIRED) -add_executable(sdbd ${sdbd_SRCS}) +ADD_EXECUTABLE(sdbd ${SDBD_SRCS}) +TARGET_LINK_LIBRARIES(sdbd -pie -lsmack -lresolv -ldl ${CMAKE_THREAD_LIBS_INIT} ${pkgs_LDFLAGS}) set_property( TARGET sdbd @@ -73,20 +123,6 @@ if(USE_FUNCTION_FS) ) endif() -ADD_DEFINITIONS("-fPIE") - -include(FindPkgConfig) - -# Get capi-system-info -pkg_check_modules(CAPI_SYSTEM_INFO REQUIRED capi-system-info libtzplatform-config) -include_directories(${CAPI_SYSTEM_INFO_INCLUDE_DIRS}) - -# Get pthreads -find_package(Threads REQUIRED) - -# Add libraries (-l...) -target_link_libraries (sdbd -pie -lsmack ${CMAKE_THREAD_LIBS_INIT} ${CAPI_SYSTEM_INFO_LDFLAGS}) - install(TARGETS sdbd DESTINATION /usr/sbin) install(FILES script/sdbd DESTINATION /etc/init.d) diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..898caea --- /dev/null +++ b/debian/changelog @@ -0,0 +1,129 @@ +sdbd (0.0.2-2) unstable; urgency=low + + * set dir permission to 777 + * Git: slp/pkgs/s/sdbd + * Tag: sdbd_0.0.2-2 + + -- Yoonki Park Wed, 18 Apr 2012 16:57:03 +0900 + +sdbd (0.0.2-1) unstable; urgency=low + + * let sshd be daemon and create sshd.pid file + * Git: slp/pkgs/s/sdbd + * Tag: sdbd_0.0.2-1 + + -- Yoonki Park Mon, 02 Apr 2012 14:37:44 +0900 + +sdbd (0.0.2) unstable; urgency=low + + * add rpm spec file + * Git: slp/pkgs/s/sdbd + * Tag: sdbd_0.0.2 + + -- Yoonki Park Mon, 19 Mar 2012 17:03:59 +0900 + +sdbd (0.0.1-13) unstable; urgency=low + + * let start_device_log enable, update maintainer information and set process working directory path to '/' + * Git: slp/pkgs/s/sdbd + * Tag: sdbd_0.0.1-13 + + -- Yoonki Park Wed, 14 Mar 2012 17:06:36 +0900 + +sdbd (0.0.1-12) unstable; urgency=low + + * update changlog file according to package policy + * Git: slp/pkgs/s/sdbd + * Tag: sdbd_0.0.1-12 + + -- Yoonki Park Mon, 05 Mar 2012 10:48:47 +0900 + +sdbd (0.0.1-11) unstable; urgency=low + + * add loopback interface checking when binding to 26099 + * Git: pkgs/s/sdbd + * Tag: sdbd_0.0.1-11 + + -- Yoonki Park Wed, 29 Feb 2012 21:09:37 +0900 + +sdbd (0.0.1-10) unstable; urgency=low + + * Add SIGTERM handler for avoid terminate on the emulator + * Git: 165.213.180.234:slp/pkgs/s/sdbd + * Tag: sdbd_0.0.1-10 + + -- Joogwan Kim Tue, 13 Dec 2011 21:26:01 +0900 + +sdbd (0.0.1-9) unstable; urgency=low + + * Remove unused files + * Git: 165.213.180.234:slp/pkgs/s/sdbd + * Tag: sdbd_0.0.1-9 + + -- Joogwan Kim Tue, 06 Dec 2011 18:59:38 +0900 + +sdbd (0.0.1-8) unstable; urgency=low + + * Modify script name to get higher priority + * Git: 165.213.180.234:slp/pkgs/s/sdbd + * Tag: sdbd_0.0.1-8 + + -- Joogwan Kim Fri, 11 Nov 2011 16:29:46 +0900 + +sdbd (0.0.1-7) unstable; urgency=low + + * Upload missing files from 0.0.1-6 + * Git: 165.213.180.234:slp/pkgs/s/sdbd + * Tag: sdbd_0.0.1-7 + + -- Jinhyung Choi Thu, 13 Oct 2011 22:19:19 +0900 + +sdbd (0.0.1-6) unstable; urgency=low + + * Supports multi configuration on linux + * Change name from Android debug bridge to Samsung Development Bridge in status_window function + * Git: 165.213.180.234:slp/pkgs/s/sdbd + * Tag: sdbd_0.0.1-6 + + -- Jinhyung Choi Thu, 13 Oct 2011 21:22:03 +0900 + +sdbd (0.0.1-5) unstable; urgency=low + + * Modify dev name from android_adb to samsung_sdb + * Git: 165.213.180.234:slp/pkgs/s/sdbd + * Tag: sdbd_0.0.1-5 + + -- Joogwan Kim Tue, 11 Oct 2011 22:52:33 +0900 + +sdbd (0.0.1-4) unstable; urgency=low + + * Change name from android_adb to samsung_sdb and removed unused + * Change sdb interface descriptor + * Git: 165.213.180.234:slp/pkgs/s/sdbd + * Tag: sdbd_0.0.1-4 + + -- Joogwan Kim Tue, 11 Oct 2011 14:35:55 +0900 + +sdbd (0.0.1-3) unstable; urgency=low + + * Just version up for upload + * Git: 165.213.180.234:slp/pkgs/s/sdbd + * Tag: sdbd_0.0.1-3 + + -- Joogwan Kim Mon, 10 Oct 2011 16:49:02 +0900 + +sdbd (0.0.1-2) unstable; urgency=low + + * Just version up for upload source package + * Git: 165.213.180.234:slp/pkgs/s/sdbd + * Tag: sdbd_0.0.1-2 + + -- Joogwan Kim Mon, 10 Oct 2011 16:28:41 +0900 + +sdbd (0.0.1-1) unstable; urgency=low + + * Initial upload + * Git: 165.213.180.234:slp/pkgs/s/sdbd + * Tag: sdbd_0.0.1-1 + + -- Joogwan Kim Sat, 26 Sep 2011 15:00:56 +0900 diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..7813681 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +5 \ No newline at end of file diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..aa3ba16 --- /dev/null +++ b/debian/control @@ -0,0 +1,10 @@ +Source: sdbd +Section: net +Priority: extra +Maintainer: Kangho Kim , Yoonki Park , Ho Namkoong +Build-Depends: debhelper (>= 5), libc6-dev +Standards-Version: 0.0.1 + +Package: sdbd +Architecture: any +Description: SDB daemon diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..6ebe31f --- /dev/null +++ b/debian/rules @@ -0,0 +1,44 @@ +#!/usr/bin/make -f + +UNAME := $(shell uname -sm) +ifneq (,$(findstring 86,$(UNAME))) + HOST_ARCH := x86 +endif + +configure: configure-stamp + +configure-stamp: + dh_testdir + touch configure-stamp + +build: build-stamp + +build-stamp: configure-stamp + dh_testdir + $(MAKE) + touch build-stamp + +install: build + dh_testdir + dh_testroot + $(MAKE) DESTDIR=$(CURDIR)/debian/tmp install + +binary: build install + dh_testdir + dh_testroot +ifeq ($(HOST_ARCH),x86) + dh_install --sourcedir=debian/tmp +else + dh_install --sourcedir=debian/tmp -XS06sdbd +endif + dh_strip + dh_gencontrol + dh_md5sums + dh_builddeb + +clean: + dh_testdir + rm -f build-stamp configure-stamp + $(MAKE) clean + dh_clean + diff --git a/debian/sdbd.install b/debian/sdbd.install new file mode 100644 index 0000000..5ac7294 --- /dev/null +++ b/debian/sdbd.install @@ -0,0 +1,3 @@ +usr/sbin/sdbd +etc/init.d/sdbd +etc/rc.d/rc3.d/S06sdbd diff --git a/packaging/sdbd.changes b/packaging/sdbd.changes index b923b27..8cba86b 100644 --- a/packaging/sdbd.changes +++ b/packaging/sdbd.changes @@ -2,7 +2,8 @@ - Version up to 3.0.1 * Thu Oct 31 2013 Junfeng Dong submit/tizen/20131011.084016@81e3d5b - Fix some runtime issue in 3.0 - +* Wed Nov 27 2013 Yoonki Park + - changed port redirection to usb0 instead of loopback * Wed Apr 04 2013 Ho Namkoong - supports platform gdbserver * Mon Dec 02 2012 Yoonki Park diff --git a/packaging/sdbd.service b/packaging/sdbd.service new file mode 100644 index 0000000..76a066e --- /dev/null +++ b/packaging/sdbd.service @@ -0,0 +1,8 @@ +[Unit] +Description=sdbd + +[Service] +Type=forking +PIDFile=/tmp/.sdbd.pid +RemainAfterExit=yes +ExecStart=/usr/sbin/sdbd diff --git a/packaging/sdbd.spec b/packaging/sdbd.spec index 65da04a..4260794 100644 --- a/packaging/sdbd.spec +++ b/packaging/sdbd.spec @@ -2,7 +2,7 @@ Name: sdbd Summary: SDB daemon -Version: 3.0.1 +Version: 3.0.2 Release: 0 License: Apache-2.0 Summary: SDB daemon @@ -16,8 +16,17 @@ Source1004: sdbd_tcp.service BuildRequires: capi-system-info-devel >= 0.2.0 BuildRequires: cmake >= 2.8.3 BuildRequires: pkgconfig(libtzplatform-config) +#BuildRequires: sec-product-features BuildRequires: pkgconfig(libsmack) +BuildRequires: pkgconfig(capi-system-info) +BuildRequires: pkgconfig(vconf) +BuildRequires: pkgconfig(glib-2.0) +BuildRequires: pkgconfig(dbus-1) +BuildRequires: pkgconfig(dbus-glib-1) +Requires(post): libprivilege-control +Requires: sys-assert Requires: dbus + %description Description: SDB daemon. @@ -27,26 +36,45 @@ Description: SDB daemon. cp %{SOURCE1003} . %build -%cmake -make %{?jobs:-j%jobs} +%if "%{?tizen_profile_name}" == "wearable" +%define wearable_profile on +%else +%define wearable_profile off +%endif +%ifarch %{ix86} +%define target_arch x86 +%else +%define target_arch arm +%endif +cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} \ + -DWEARABLE_PROFILE=%{wearable_profile} \ + -DTARGET_ARCH=%{target_arch} +make %{?jobs:-j%jobs} %install -%make_install +mkdir -p %{buildroot}/usr/share/license +cp LICENSE %{buildroot}/usr/share/license/%{name} +%make_install +mkdir -p %{buildroot}%{_libdir}/systemd/system mkdir -p %{buildroot}%{_unitdir} -%if %{with emulator} -install -m 0644 %SOURCE1002 %{buildroot}%{_unitdir}/sdbd.service -mkdir -p %{buildroot}/%{_unitdir}/emulator.target.wants -ln -s %{_unitdir}/sdbd.service %{buildroot}/%{_unitdir}/emulator.target.wants/ +%ifarch %{ix86} +install -m 0644 %SOURCE1002 %{buildroot}%{_libdir}/systemd/system/sdbd.service +mkdir -p %{buildroot}/%{_libdir}/systemd/system/emulator.target.wants +ln -s %{_libdir}/systemd/system/sdbd.service %{buildroot}/%{_libdir}/systemd/system/emulator.target.wants/ %else install -m 0644 %SOURCE1001 %{buildroot}%{_unitdir}/sdbd.service install -m 0644 %SOURCE1004 %{buildroot}%{_unitdir}/sdbd_tcp.service +mkdir -p %{buildroot}/%{_libdir}/systemd/system/multi-user.target.wants +ln -s %{_libdir}/systemd/system/sdbd.service %{buildroot}/%{_libdir}/systemd/system/multi-user.target.wants/ %endif mkdir -p %{buildroot}%{_prefix}/sbin install -m 755 script/sdk_launch %{buildroot}%{_prefix}/sbin/ +mkdir -p %{buildroot}/usr/bin +install -m 755 script/profile_command %{buildroot}/usr/bin/ %post . %{_sysconfdir}/tizen-platform.conf @@ -67,10 +95,13 @@ fi %{_prefix}/sbin/sdk_launch %attr(0755, root, root) %{_sysconfdir}/init.d/sdbd %{_unitdir}/sdbd.service -%if %{with emulator} -%{_unitdir}/emulator.target.wants/sdbd.service +%ifarch %{ix86} +%{_libdir}/systemd/system/emulator.target.wants/sdbd.service %else %{_unitdir}/sdbd_tcp.service +%{_libdir}/systemd/system/multi-user.target.wants/sdbd.service %endif +/usr/share/license/%{name} +/usr/bin/profile_command %changelog diff --git a/packaging/sdbd_device.service b/packaging/sdbd_device.service index 48f0e6d..949ca4e 100644 --- a/packaging/sdbd_device.service +++ b/packaging/sdbd_device.service @@ -1,6 +1,7 @@ [Unit] Description=sdbd Requires=tizen-system-env.service +After=tmp.mount [Service] Type=forking @@ -8,3 +9,6 @@ EnvironmentFile=-/run/tizen-system-env PIDFile=/tmp/.sdbd.pid RemainAfterExit=yes ExecStart=/usr/sbin/sdbd + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/packaging/sdbd_emulator.service b/packaging/sdbd_emulator.service index 579381a..1a2f298 100644 --- a/packaging/sdbd_emulator.service +++ b/packaging/sdbd_emulator.service @@ -1,6 +1,8 @@ [Unit] Description=sdbd Before=sensord.service +After=tmp.mount dbus.service +#DefaultDependencies=false [Service] Type=forking @@ -8,7 +10,9 @@ Environment=DISPLAY=:0 PIDFile=/tmp/.sdbd.pid RemainAfterExit=yes SmackProcessLabel=User -ExecStart=/bin/sh -c "/usr/sbin/sdbd `/usr/bin/awk '{match($0, /sdb_port=([0-9]+)/,port_match); match($0, /vm_name=([^, ]*)/,vm_match); print \"--emulator=\" vm_match[1] \":\" port_match[1] \" --connect-to=10.0.2.2:26099\" \" --sensors=10.0.2.2:\"port_match[1]+3 \" --listen-port=\"port_match[1]+1 }' /proc/cmdline`" +#ExecStartPre=/bin/bash -c "/bin/echo '10.0.2.15/32 system::debugging_network' >> /smack/netlabel" +ExecStart=/bin/sh -c "/usr/sbin/sdbd `/usr/bin/awk '{match($0, /sdb_port=([0-9]+)/,port_match); match($0, /vm_name=([^, ]*)/,vm_match); print \"--emulator=\" vm_match[1] \":\" port_match[1] \" --connect-to=10.0.2.2:26099\" \" --sensors=10.0.2.2:\"port_match[1]+3 }' /proc/cmdline`" [Install] WantedBy=emulator.target + diff --git a/script/profile_command b/script/profile_command new file mode 100755 index 0000000..cdaef64 --- /dev/null +++ b/script/profile_command @@ -0,0 +1,90 @@ +#!/bin/bash + +VERSION="4.0" +KILL=/usr/bin/killall +MANAGER=/usr/bin/da_manager +FIND=/usr/bin/find +GETAPPINSTALLPATH="/usr/bin/pkgcmd -a" +PORTFILE=/tmp/port.da + +print_usage() +{ + echo "usage: profile_command [options]" + echo "Options:" + echo "getprobemap get da_api_map" + echo "killmanager terminate da_manager" + echo "runmanager execute da_manager" + echo "findunittest find unittest project" + echo "getversion get version" + echo "killvalgrind kill valgrind process" +} + +get_probe_map() +{ + /bin/cat /usr/lib/da_api_map +} + +kill_manager() +{ + $KILL $MANAGER + /bin/rm -f $PORTFILE +} + +run_manager() +{ + kill_manager + $MANAGER +} + +find_unittest() +{ + $FIND `$GETAPPINSTALLPATH | /usr/bin/awk '{if (FNR==1) printf $NF}'` -name *.unittest +} + +process_list() +{ + /bin/ps -ewo pid,cmd +} + +get_version() +{ + echo $VERSION +} + +kill_valgrind() +{ + /bin/ps ax | /bin/grep "/home/developer/sdk_tools/valgrind/usr/bin/valgrin[d]" | /usr/bin/awk '{print "kill -3 " $1}' | /bin/sh +} + +if test $# -ne 1 ; then + print_usage + exit 1 +fi + +case "$1" in + killmanager) + kill_manager + ;; + runmanager) + run_manager + ;; + findunittest) + find_unittest + ;; + process) + process_list + ;; + getversion) + get_version + ;; + killvalgrind) + kill_valgrind + ;; + getprobemap) + get_probe_map + ;; + *) + echo "Unknown option!" + print_usage + ;; +esac diff --git a/script/sdk_launch b/script/sdk_launch index 0c01f1b..941f236 100755 --- a/script/sdk_launch +++ b/script/sdk_launch @@ -11,13 +11,22 @@ SDK_TOOLS_PATH=${TZ_SDK_TOOLS} print_usage() { - echo "usage: $0 -p -e -m [-P ] [-attach ] -t []" + echo "usage: $0 [-a ] [-p ] [-e ] -m [-P ] [-attach ] -t []" } first="true" until [ -z "$1" ]; do case "$1" in + -a) + if [ -z "$2" ] + then + print_usage + exit 1; + fi + appid=$2 + shift 2; + ;; -p) if [ -z "$2" ] then @@ -111,6 +120,13 @@ until [ -z "$1" ]; do esac done +if [ "" != "$appid" ] +then + launch_app_arg1=$appid +else + launch_app_arg1=$pkgid.$exe +fi + if [ "$mode" = "debug" ] then if [ "" != "$attach_id" ] diff --git a/sdbd.manifest b/sdbd.manifest new file mode 100644 index 0000000..1effc20 --- /dev/null +++ b/sdbd.manifest @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/commandline.c b/src/commandline.c index cbc6164..740cd2b 100644 --- a/src/commandline.c +++ b/src/commandline.c @@ -802,7 +802,7 @@ static const char *find_product_out_path(const char *hint) */ if (sdb_dirstart(hint) != NULL) { if (getcwd(path_buf, sizeof(path_buf)) == NULL) { - fprintf(stderr, "sdb: Couldn't get CWD: %s\n", strerror(errno)); + fprintf(stderr, "sdb: Couldn't get CWD: errno:%d\n", errno); return NULL; } if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) { diff --git a/src/commandline_sdbd.c b/src/commandline_sdbd.c index ec16a0d..63850f3 100644 --- a/src/commandline_sdbd.c +++ b/src/commandline_sdbd.c @@ -36,6 +36,22 @@ */ int split_host_port(const char *optarg, char **host, int *port); +/*! + * @define print_nullable(s) + * Takes string (const char *) and returns it or "(null)" literal + * in case \c s is NULL. + */ +#define print_nullable(s) \ + (((s) == NULL) ? "(NULL)" : (s)) + + +static void print_sdbd_command(FILE *stream, SdbdCommandlineArgs *sdbd_args) { + fprintf(stream, "sdbd_port [%d] \n", sdbd_args->sdbd_port); + fprintf(stream, "emulator [%s:%d] \n", print_nullable(sdbd_args->emulator.host), sdbd_args->emulator.port); + fprintf(stream, "sdb [%s:%d] \n", print_nullable(sdbd_args->sdb.host), sdbd_args->sdb.port); + fprintf(stream, "sensors [%s:%d] \n", print_nullable(sdbd_args->sensors.host), sdbd_args->sensors.port); +} + int parse_sdbd_commandline(SdbdCommandlineArgs *sdbd_args, int argc, char *argv[]) { int split_retval; @@ -69,6 +85,7 @@ int parse_sdbd_commandline(SdbdCommandlineArgs *sdbd_args, int argc, char *argv[ if (sdbd_args->sdbd_port < 0) { sdbd_args->sdbd_port = DEFAULT_SDB_LOCAL_TRANSPORT_PORT; } + print_sdbd_command(stdout, sdbd_args); break; case ARG_S_SENSORS: split_retval = split_host_port(optarg, @@ -77,6 +94,7 @@ int parse_sdbd_commandline(SdbdCommandlineArgs *sdbd_args, int argc, char *argv[ if (split_retval != SDBD_COMMANDLINE_SUCCESS) { return split_retval; } + print_sdbd_command(stdout, sdbd_args); break; case ARG_S_SDB: split_retval = split_host_port(optarg, @@ -85,11 +103,13 @@ int parse_sdbd_commandline(SdbdCommandlineArgs *sdbd_args, int argc, char *argv[ if (split_retval != SDBD_COMMANDLINE_SUCCESS) { return split_retval; } + print_sdbd_command(stdout, sdbd_args); break; case ARG_S_SDBD_LISTEN_PORT: if (sscanf(optarg, "%d", &sdbd_args->sdbd_port) < 1) { return SDBD_COMMANDLINE_FAILURE; } + print_sdbd_command(stdout, sdbd_args); break; case ARG_S_HELP: return SDBD_COMMANDLINE_HELP; @@ -104,11 +124,15 @@ int parse_sdbd_commandline(SdbdCommandlineArgs *sdbd_args, int argc, char *argv[ } } + print_sdbd_command(stdout, sdbd_args); + return SDBD_COMMANDLINE_SUCCESS; } void apply_sdbd_commandline_defaults(SdbdCommandlineArgs *sdbd_args) { + sdbd_args->emulator.port = -1; + sdbd_args->sensors.host = strdup(QEMU_FORWARD_IP); sdbd_args->sensors.port = DEFAULT_SENSORS_LOCAL_TRANSPORT_PORT; diff --git a/src/file_sync_client.c b/src/file_sync_client.c index 0e80efd..3ba3770 100644 --- a/src/file_sync_client.c +++ b/src/file_sync_client.c @@ -216,7 +216,7 @@ static int write_data_file(int fd, const char *path, syncsendbuf *sbuf) lfd = sdb_open(path, O_RDONLY); if(lfd < 0) { - fprintf(stderr,"cannot open '%s': %s\n", path, strerror(errno)); + fprintf(stderr,"cannot open '%s': errno:%d\n", path, errno); return -1; } @@ -231,7 +231,7 @@ static int write_data_file(int fd, const char *path, syncsendbuf *sbuf) if(ret < 0) { if(errno == EINTR) continue; - fprintf(stderr,"cannot read '%s': %s\n", path, strerror(errno)); + fprintf(stderr,"cannot read '%s': errno:%d\n", path, errno); break; } @@ -279,7 +279,7 @@ static int write_data_link(int fd, const char *path, syncsendbuf *sbuf) len = readlink(path, sbuf->data, SYNC_DATA_MAX-1); if(len < 0) { - fprintf(stderr, "error reading link '%s': %s\n", path, strerror(errno)); + fprintf(stderr, "error reading link '%s': errno:%d\n", path, errno); return -1; } sbuf->data[len] = '\0'; @@ -324,7 +324,7 @@ static int sync_send(int fd, const char *lpath, const char *rpath, // this requires that we read the entire file into memory. lfd = sdb_open(lpath, O_RDONLY); if(lfd < 0) { - fprintf(stderr,"cannot open '%s': %s\n", lpath, strerror(errno)); + fprintf(stderr,"cannot open '%s': errno:%d\n", lpath, errno); return -1; } @@ -469,7 +469,7 @@ int sync_recv(int fd, const char *rpath, const char *lpath) mkdirs((char *)lpath); lfd = sdb_creat(lpath, 0644); if(lfd < 0) { - fprintf(stderr,"cannot create '%s': %s\n", lpath, strerror(errno)); + fprintf(stderr,"cannot create '%s': errno:%d\n", lpath, errno); return -1; } goto handle_data; @@ -499,7 +499,7 @@ int sync_recv(int fd, const char *rpath, const char *lpath) } if(writex(lfd, buffer, len)) { - fprintf(stderr,"cannot write '%s': %s\n", rpath, strerror(errno)); + fprintf(stderr,"cannot write '%s': errno:%d\n", rpath, errno); sdb_close(lfd); return -1; } @@ -614,7 +614,7 @@ static int local_build_list(copyinfo **filelist, d = opendir(lpath); if(d == 0) { - fprintf(stderr,"cannot open '%s': %s\n", lpath, strerror(errno)); + fprintf(stderr,"cannot open '%s': errno:%d\n", lpath, errno); return -1; } @@ -644,7 +644,7 @@ static int local_build_list(copyinfo **filelist, } else { ci = mkcopyinfo(lpath, rpath, name, 0); if(lstat(ci->src, &st)) { - fprintf(stderr,"cannot stat '%s': %s\n", ci->src, strerror(errno)); + fprintf(stderr,"cannot stat '%s': errno:%d\n", ci->src, errno); closedir(d); return -1; @@ -758,7 +758,7 @@ int do_sync_push(const char *lpath, const char *rpath, int verifyApk, int isUtf8 } if(stat(lpath, &st)) { - fprintf(stderr,"cannot stat '%s': %s\n", lpath, strerror(errno)); + fprintf(stderr,"cannot stat '%s': errno:%d\n", lpath, errno); sync_quit(fd); return 1; } diff --git a/src/file_sync_service.c b/src/file_sync_service.c index 55785ce..2efe0ea 100644 --- a/src/file_sync_service.c +++ b/src/file_sync_service.c @@ -34,6 +34,7 @@ #include "sdb.h" #include "file_sync_service.h" #include "sdktools.h" +#include "sdbd_plugin.h" #define SYNC_TIMEOUT 15 @@ -92,6 +93,13 @@ static void set_syncfile_smack_label(char *src) { if (smack_setlabel(src, label, SMACK_LABEL_ACCESS) == -1) { D("unable to set sync file smack label %s due to %s\n", label, strerror(errno)); } + + /* Todo: The following code is from tizen 2.4 + rc = security_server_label_access(src, label); + if (rc != SECURITY_SERVER_API_SUCCESS) { + D("unable to set sync file smack label %s due to %d\n", label, errno); + } + */ free(label); } } else{ @@ -102,6 +110,13 @@ static void set_syncfile_smack_label(char *src) { if (smack_setlabel(src, SMACK_SYNC_FILE_LABEL, SMACK_LABEL_ACCESS) == -1) { D("unable to set sync file smack label %s due to %s\n", SMACK_SYNC_FILE_LABEL, strerror(errno)); } + + /* Todo: The following code is from tizen 2.4 + rc = security_server_label_access(src, SMACK_SYNC_FILE_LABEL); + if (rc != SECURITY_SERVER_API_SUCCESS) { + D("unable to set sync file smack label %s due to %d\n", SMACK_SYNC_FILE_LABEL, errno); + } + */ } } @@ -117,12 +132,12 @@ static int sync_send_label_notify(int s, const char *path, int success) static void sync_read_label_notify(int s) { - char buffer[512] = {0,}; + char buffer[512 + 1] = {0,}; while (1) { - int len = sdb_read(s, buffer, sizeof(buffer)); + int len = sdb_read(s, buffer, sizeof(buffer) - 1); if (len < 0) { - D("sync notify read error:%s\n", strerror(errno)); + D("sync notify read errno:%d\n", errno); exit(-1); } @@ -130,6 +145,7 @@ static void sync_read_label_notify(int s) D("sync notify child process exit\n"); exit(-1); } + buffer[len] = '\0'; char *path = buffer; path++; path++; @@ -158,7 +174,7 @@ static int mkdirs(int noti_fd, char *name) sync_send_label_notify(noti_fd, name, 1); } if((ret < 0) && (errno != EEXIST)) { - D("mkdir(\"%s\") -> %s\n", name, strerror(errno)); + D("mkdir(\"%s\") -> errno:%d\n", name, errno); *x = '/'; return ret; } @@ -179,7 +195,7 @@ static int do_stat(int s, const char *path) msg.stat.mode = 0; msg.stat.size = 0; msg.stat.time = 0; - D("failed to stat %s due to: %s\n", path, strerror(errno)); + D("failed to stat %s due to: errno:%d\n", path, errno); } else { msg.stat.mode = htoll(st.st_mode); msg.stat.size = htoll(st.st_size); @@ -200,6 +216,9 @@ static int do_list(int s, const char *path) char tmp[1024 + 256 + 1]; char *fname; + char dirent_buffer[ sizeof(struct dirent) + 260 + 1 ] = {0,}; + struct dirent *dirent_r = (struct dirent*)dirent_buffer; + len = strlen(path); memcpy(tmp, path, len); tmp[len] = '/'; @@ -209,11 +228,11 @@ static int do_list(int s, const char *path) d = opendir(path); if(d == NULL) { - D("failed to open dir due to: %s\n", strerror(errno)); + D("failed to open dir due to: errno:%d\n", errno); goto done; } - while((de = readdir(d))) { + while((readdir_r(d, dirent_r, &de) == 0) && de) { int len = strlen(de->d_name); /* not supposed to be possible, but @@ -222,7 +241,7 @@ static int do_list(int s, const char *path) continue; } - strcpy(fname, de->d_name); + s_strncpy(fname, de->d_name, sizeof tmp); if(lstat(tmp, &st) == 0) { msg.dent.mode = htoll(st.st_mode); msg.dent.size = htoll(st.st_size); @@ -267,7 +286,44 @@ static int fail_message(int s, const char *reason) static int fail_errno(int s) { - return fail_message(s, strerror(errno)); + char buf[512]; + + strerror_r(s, buf, sizeof(buf)); + + return fail_message(s, buf); +} + +// FIXME: should get the following paths with api later but, do it for simple and not having dependency on other packages +#define VAR_ABS_PATH "/opt/var" +#define CMD_MEDIADB_UPDATE "/usr/bin/mediadb-update" +#define MEDIA_CONTENTS_PATH1 "/opt/media" +#define MEDIA_CONTENTS_PATH2 "/opt/usr/media" +#define MEDIA_CONTENTS_PATH3 "/opt/storage/sdcard" + +static void sync_mediadb(char *path) { + if (access(CMD_MEDIADB_UPDATE, F_OK) != 0) { + D("%s: command not found\n", CMD_MEDIADB_UPDATE); + return; + } + + if (strstr(path, VAR_ABS_PATH) == path) { + path += 4; + } + + if (strstr(path, MEDIA_CONTENTS_PATH1) != NULL) { + char *arg_list[] = {CMD_MEDIADB_UPDATE, "-r", MEDIA_CONTENTS_PATH1, NULL}; + spawn(CMD_MEDIADB_UPDATE, arg_list); + D("media db update done to %s\n", MEDIA_CONTENTS_PATH1); + } else if (strstr(path, MEDIA_CONTENTS_PATH2) != NULL) { + char *arg_list[] = {CMD_MEDIADB_UPDATE, "-r", MEDIA_CONTENTS_PATH2, NULL}; + spawn(CMD_MEDIADB_UPDATE, arg_list); + D("media db update done to %s\n", MEDIA_CONTENTS_PATH2); + } else if (strstr(path, MEDIA_CONTENTS_PATH3) != NULL) { + char *arg_list[] = {CMD_MEDIADB_UPDATE, "-r", MEDIA_CONTENTS_PATH3, NULL}; + spawn(CMD_MEDIADB_UPDATE, arg_list); + D("media db update done to %s\n", MEDIA_CONTENTS_PATH3); + } + return; } static int handle_send_file(int s, int noti_fd, char *path, mode_t mode, char *buffer) @@ -344,6 +400,7 @@ static int handle_send_file(int s, int noti_fd, char *path, mode_t mode, char *b return -1; } sync_send_label_notify(noti_fd, path, 1); + sync_mediadb(path); return 0; fail: @@ -403,12 +460,30 @@ static int handle_send_link(int s, int noti_fd, char *path, char *buffer) } #endif /* HAVE_SYMLINKS */ +static int is_support_push() +{ + return (!strncmp(g_capabilities.filesync_support, SDBD_CAP_RET_PUSHPULL, strlen(SDBD_CAP_RET_PUSHPULL)) + || !strncmp(g_capabilities.filesync_support, SDBD_CAP_RET_PUSH, strlen(SDBD_CAP_RET_PUSH))); +} + +static int is_support_pull() +{ + return (!strncmp(g_capabilities.filesync_support, SDBD_CAP_RET_PUSHPULL, strlen(SDBD_CAP_RET_PUSHPULL)) + || !strncmp(g_capabilities.filesync_support, SDBD_CAP_RET_PULL, strlen(SDBD_CAP_RET_PULL))); +} + static int do_send(int s, int noti_fd, char *path, char *buffer) { char *tmp; mode_t mode; int is_link, ret; + // Check the capability for file push support. + if(!is_support_push()) { + fail_message(s, "NO support file push."); + return -1; + } + tmp = strrchr(path,','); if(tmp) { *tmp = 0; @@ -427,6 +502,10 @@ static int do_send(int s, int noti_fd, char *path, char *buffer) mode = 0644; // set default permission value in most of unix system. is_link = 0; } + if (is_pkg_file_path(path)) { + mode = 0644; + is_link = 0; + } // sdb does not allow to check that file exists or not. After deleting old file and creating new file again unconditionally. sdb_unlink(path); @@ -457,6 +536,12 @@ static int do_recv(int s, const char *path, char *buffer) syncmsg msg; int fd, r; + // Check the capability for file push support. + if (!is_support_pull()) { + fail_message(s, "NO support file pull."); + return -1; + } + fd = sdb_open(path, O_RDONLY); if(fd < 0) { if(fail_errno(s)) return -1; diff --git a/src/file_sync_service.h b/src/file_sync_service.h index 61b462a..94a52b6 100644 --- a/src/file_sync_service.h +++ b/src/file_sync_service.h @@ -76,6 +76,7 @@ typedef union { } syncmsg; void init_sdk_sync_permit_rule_regx(void); + void file_sync_service(int fd, void *cookie); void file_sync_subproc(int fd, void *cookie); int do_sync_ls(const char *path); diff --git a/src/properties.c b/src/properties.c index 7594100..42e5785 100644 --- a/src/properties.c +++ b/src/properties.c @@ -240,8 +240,8 @@ static int connectToServer(const char* fileName) if (cc < 0) { // ENOENT means socket file doesn't exist // ECONNREFUSED means socket exists but nobody is listening - D("AF_UNIX connect failed for '%s': %s\n", - fileName, strerror(errno)); + D("AF_UNIX connect failed for '%s': errno:%d\n", + fileName, errno); sdb_close(sock); return -1; } diff --git a/src/qemu_pipe.h b/src/qemu_pipe.h index 5d6e87e..0cb5f93 100644 --- a/src/qemu_pipe.h +++ b/src/qemu_pipe.h @@ -67,7 +67,7 @@ qemu_pipe_open(const char* pipeName) fd = open("/dev/qemu_pipe", O_RDWR); if (fd < 0) { - D("%s: Could not open /dev/qemu_pipe: %s", __FUNCTION__, strerror(errno)); + D("%s: Could not open /dev/qemu_pipe: errno:%d", __FUNCTION__, errno); //errno = ENOSYS; return -1; } @@ -76,7 +76,7 @@ qemu_pipe_open(const char* pipeName) ret = TEMP_FAILURE_RETRY(write(fd, buff, buffLen+1)); if (ret != buffLen+1) { - D("%s: Could not connect to %s pipe service: %s", __FUNCTION__, pipeName, strerror(errno)); + D("%s: Could not connect to %s pipe service: errno:%d", __FUNCTION__, pipeName, errno); if (ret == 0) { errno = ECONNRESET; } else if (ret > 0) { diff --git a/src/sdb.c b/src/sdb.c index 8b9f7cc..2fff648 100644 --- a/src/sdb.c +++ b/src/sdb.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- - * +/* * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved * * Licensed under the Apache License, Version 2.0 (the License); @@ -29,6 +28,8 @@ #include #include #include +#include +#include #include "sysdeps.h" #include "sdb.h" @@ -36,6 +37,8 @@ #if !SDB_HOST #include "commandline_sdbd.h" #endif +#include "utils.h" +#include "sdktools.h" #if !SDB_HOST #include @@ -44,8 +47,18 @@ #include "usb_vendors.h" #endif #include +#include +#include "utils.h" #define PROC_CMDLINE_PATH "/proc/cmdline" -#define SYSTEM_INFO_KEY_MODEL "http://tizen.org/system/model_name" +#define USB_SERIAL_PATH "/sys/class/usb_mode/usb0/iSerial" + +#include +#include +#include +#include +#define GUEST_IP_INTERFACE "eth0" + +SDB_MUTEX_DEFINE(zone_check_lock); #if SDB_TRACE SDB_MUTEX_DEFINE( D_lock ); #endif @@ -72,18 +85,33 @@ int is_emulator(void) { #endif } +int is_container_enabled(void) { + bool value; + int ret; + ret = system_info_get_platform_bool("tizen.org/feature/container", &value); + if (ret != SYSTEM_INFO_ERROR_NONE) { + D("failed to get container information: %d\n", errno); + return 0; + } else { + D("tizen container: %d\n", value); + if (value == true) + return 1; + else + return 0; + } +} + +void* g_sdbd_plugin_handle = NULL; +SDBD_PLUGIN_CMD_PROC_PTR sdbd_plugin_cmd_proc = NULL; + void handle_sig_term(int sig) { #ifdef SDB_PIDPATH if (access(SDB_PIDPATH, F_OK) == 0) sdb_unlink(SDB_PIDPATH); #endif - //kill(getpgid(getpid()),SIGTERM); - //killpg(getpgid(getpid()),SIGTERM); - if (!is_emulator()) { - exit(0); - } else { - // do nothing on a emulator - } + char *cmd1_args[] = {"/usr/bin/killall", "/usr/bin/debug_launchpad_preloading_preinitializing_daemon", NULL}; + spawn("/usr/bin/killall", cmd1_args); + sdb_sleep_ms(1000); } static const char *sdb_device_banner = "device"; @@ -103,7 +131,7 @@ void fatal_errno(const char *fmt, ...) { va_list ap; va_start(ap, fmt); - fprintf(stderr, "error: %s: ", strerror(errno)); + fprintf(stderr, "errno: %d: ", errno); vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); va_end(ap); @@ -319,7 +347,7 @@ static void send_close(unsigned local, unsigned remote, atransport *t) p->msg.arg1 = remote; send_packet(p, t); } -static int device_status = 0; // 0:online, 1: password locked later + static void send_connect(atransport *t) { D("Calling send_connect \n"); @@ -330,6 +358,11 @@ static void send_connect(atransport *t) char device_name[256]={0,}; int r = 0; + int status = 0; + if (is_pwlocked()) { + status = 1; + t->connection_state = CS_PWLOCK; + } if (is_emulator()) { r = get_emulator_name(device_name, sizeof device_name); @@ -337,9 +370,9 @@ static void send_connect(atransport *t) r = get_device_name(device_name, sizeof device_name); } if (r < 0) { - snprintf((char*) cp->data, sizeof cp->data, "%s::%s::%d", sdb_device_banner, DEFAULT_DEVICENAME, device_status); + snprintf((char*) cp->data, sizeof cp->data, "%s::%s::%d", sdb_device_banner, DEFAULT_DEVICENAME, status); } else { - snprintf((char*) cp->data, sizeof cp->data, "%s::%s::%d", sdb_device_banner, device_name, device_status); + snprintf((char*) cp->data, sizeof cp->data, "%s::%s::%d", sdb_device_banner, device_name, status); } D("CNXN data:%s\n", (char*)cp->data); @@ -353,6 +386,21 @@ static void send_connect(atransport *t) #endif } +static void send_device_status() +{ + D("broadcast device status\n"); + apacket* cp = get_apacket(); + cp->msg.command = A_STAT; + cp->msg.arg0 = is_pwlocked(); + cp->msg.arg1 = 0; + + broadcast_transport(cp); + + //all broadcasted packets are memory copied + //so, we should call put_apacket + put_apacket(cp); +} + static char *connection_state_name(atransport *t) { if (t == NULL) { @@ -388,7 +436,8 @@ static int get_str_cmdline(char *src, char *dest, char str[], int str_size) { return -1; } - s_strncpy(str, s + strlen(dest), len); + strncpy(str, s + strlen(dest), len); + str[len]='\0'; return len; } @@ -415,7 +464,7 @@ int get_emulator_name(char str[], int str_size) { int get_device_name(char str[], int str_size) { char *value = NULL; - int r = system_info_get_platform_string(SYSTEM_INFO_KEY_MODEL, &value); + int r = system_info_get_platform_string("http://tizen.org/system/model_name", &value); if (r != SYSTEM_INFO_ERROR_NONE) { D("fail to get system model:%d\n", errno); return -1; @@ -444,6 +493,60 @@ int get_device_name(char str[], int str_size) { return -1; } +static int get_cmdline_value(char *split, char str[], int str_size) { + char cmdline[512]; + int fd = unix_open(PROC_CMDLINE_PATH, O_RDONLY); + + if (fd < 0) { + D("fail to read /proc/cmdline\n"); + return -1; + } + if(read_line(fd, cmdline, sizeof(cmdline))) { + D("qemu cmd: %s\n", cmdline); + if (get_str_cmdline(cmdline, split, str, str_size) < 1) { + D("could not get the (%s) value from cmdline\n", split); + sdb_close(fd); + return -1; + } + } + sdb_close(fd); + return 0; +} + +int get_emulator_hostip(char str[], int str_size) { + return get_cmdline_value("host_ip=", str, str_size); +} + +int get_emulator_guestip(char str[], int str_size) { + int s; + struct ifreq ifr; + struct sockaddr_in *sin; + + s = socket(AF_INET, SOCK_DGRAM, 0); + if(s < 0) { + D("socket error\n"); + return -1; + } + + snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", GUEST_IP_INTERFACE); + if(ioctl(s, SIOCGIFHWADDR, &ifr) < 0) { + D("ioctl hwaddr error\n"); + sdb_close(s); + return -1; + } + + if(ioctl(s, SIOCGIFADDR, &ifr) < 0) { + D("ioctl addr error\n"); + sdb_close(s); + return -1; + } + sin = (struct sockaddr_in *)&ifr.ifr_addr; + snprintf(str, str_size, "%s", inet_ntoa(sin->sin_addr)); + sdb_close(s); + + return 0; +} + void parse_banner(char *banner, atransport *t) { char *type, *product, *end; @@ -535,17 +638,22 @@ void handle_packet(apacket *p, atransport *t) break; case A_OPEN: /* OPEN(local-id, 0, "destination") */ - if(t->connection_state != CS_OFFLINE) { - char *name = (char*) p->data; - name[p->msg.data_length > 0 ? p->msg.data_length - 1 : 0] = 0; - s = create_local_service_socket(name); - if(s == 0) { - send_close(0, p->msg.arg0, t); - } else { - s->peer = create_remote_socket(p->msg.arg0, t); - s->peer->peer = s; - send_ready(s->id, s->peer->id, t); - s->ready(s); + if (is_pwlocked() && t->connection_state == CS_PWLOCK) { // in case of already locked before get A_CNXN + D("open failed due to password locked before get A_CNXN:%d\n", t->connection_state); + send_close(0, p->msg.arg0, t); + } else { + if(t->connection_state != CS_OFFLINE) { + char *name = (char*) p->data; + name[p->msg.data_length > 0 ? p->msg.data_length - 1 : 0] = 0; + s = create_local_service_socket(name); + if(s == 0) { + send_close(0, p->msg.arg0, t); + } else { + s->peer = create_remote_socket(p->msg.arg0, t); + s->peer->peer = s; + send_ready(s->id, s->peer->id, t); + s->ready(s); + } } } break; @@ -811,6 +919,10 @@ static void sdb_cleanup(void) // if(required_pid > 0) { // kill(required_pid, SIGKILL); // } + if (g_sdbd_plugin_handle) { + dlclose(g_sdbd_plugin_handle); + g_sdbd_plugin_handle = NULL; + } } void start_logging(void) @@ -1096,6 +1208,40 @@ static void init_drop_privileges() { #endif } +int is_pwlocked(void) { + int pwlock_status = 0; + int pwlock_type = 0; + + if (vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &pwlock_status)) { + pwlock_status = 0; + D("failed to get pw lock status\n"); + } +#ifdef _WEARABLE + D("wearable lock applied\n"); + // for wearable which uses different VCONF key (lock type) + if (vconf_get_int(VCONFKEY_SETAPPL_PRIVACY_LOCK_TYPE_INT, &pwlock_type)) { + pwlock_type = 0; + D("failed to get pw lock type\n"); + } + if ((pwlock_status == VCONFKEY_IDLE_LOCK) && (pwlock_type != SETTING_PRIVACY_LOCK_TYPE_NONE)) { + D("device has been locked\n"); + return 1; // locked! + } +#else + D("mobile lock applied\n"); + // for mobile + if (vconf_get_int(VCONFKEY_SETAPPL_SCREEN_LOCK_TYPE_INT, &pwlock_type)) { + pwlock_type = 0; + D("failed to get pw lock type\n"); + } + if (pwlock_status == VCONFKEY_IDLE_LOCK && ((pwlock_type != SETTING_SCREEN_LOCK_TYPE_NONE) && (pwlock_type != SETTING_SCREEN_LOCK_TYPE_SWIPE))) { + D("device has been locked\n"); + return 1; // locked! + } +#endif + return 0; // unlocked! +} + int should_drop_privileges() { if (rootshell_mode == 1) { // if root, then don't drop return 0; @@ -1103,20 +1249,139 @@ int should_drop_privileges() { return 1; } +static void *pwlock_tmp_cb(void *x) +{ + int status = is_pwlocked(); + /** + * FIXME: make it callback using vconf_notify_key_changed + */ + + while(1) { + if (status != is_pwlocked()) { + send_device_status(); + status = is_pwlocked(); + } + sdb_sleep_ms(3000); + } + return 0; +} + +void register_pwlock_cb() { + D("registerd vconf callback\n"); + + sdb_thread_t t; + if(sdb_thread_create( &t, pwlock_tmp_cb, NULL)){ + D("cannot create service thread\n"); + return; + } +} + +#include +#include +#include + +#define BOOTING_DONE_SIGNAL "BootingDone" +#define DEVICED_CORE_INTERFACE "org.tizen.system.deviced.core" +#define SDBD_BOOT_INFO_FILE "/tmp/sdbd_boot_info" + +static DBusHandlerResult __sdbd_dbus_signal_filter(DBusConnection *conn, + DBusMessage *message, void *user_data) { + D("got dbus message\n"); + const char *interface; + + DBusError error; + dbus_error_init(&error); + + interface = dbus_message_get_interface(message); + if (interface == NULL) { + D("reject by security issue - no interface\n"); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + if (dbus_message_is_signal(message, DEVICED_CORE_INTERFACE, + BOOTING_DONE_SIGNAL)) { + booting_done = 1; + if (access(SDBD_BOOT_INFO_FILE, F_OK) == 0) { + D("booting is done before\n"); + } else { + FILE *f = fopen(SDBD_BOOT_INFO_FILE, "w"); + if (f != NULL) { + fprintf(f, "%d", 1); + fclose(f); + } + } + D("booting is done\n"); + } + + D("handled dbus message\n"); + return DBUS_HANDLER_RESULT_HANDLED; +} + +static void *bootdone_cb(void *x) { + int MAX_LOCAL_BUFSZ = 128; + DBusError error; + DBusConnection *bus; + char rule[MAX_LOCAL_BUFSZ]; + GMainLoop *mainloop; + + g_type_init(); + + dbus_error_init(&error); + bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error); + if (!bus) { + D("Failed to connect to the D-BUS daemon: %s", error.message); + dbus_error_free(&error); + return -1; + } + dbus_connection_setup_with_g_main(bus, NULL); + + snprintf(rule, MAX_LOCAL_BUFSZ, "type='signal',interface='%s'", + DEVICED_CORE_INTERFACE); + /* listening to messages */ + dbus_bus_add_match(bus, rule, &error); + if (dbus_error_is_set(&error)) { + D("Fail to rule set: %s", error.message); + dbus_error_free(&error); + return -1; + } + + if (dbus_connection_add_filter(bus, __sdbd_dbus_signal_filter, NULL, NULL) + == FALSE) + return -1; + + D("booting signal initialized\n"); + mainloop = g_main_loop_new(NULL, FALSE); + g_main_loop_run(mainloop); + + D("dbus loop exited"); + + return 0; +} + +void register_bootdone_cb() { + D("registerd bootdone callback\n"); + + sdb_thread_t t; + if (sdb_thread_create(&t, bootdone_cb, NULL)) { + D("cannot create service thread\n"); + return; + } +} + int set_developer_privileges() { - gid_t groups[] = { GID_DEVELOPER, SID_APP_LOGGING, SID_SYS_LOGGING, SID_INPUT }; + gid_t groups[] = { SID_DEVELOPER, SID_APP_LOGGING, SID_SYS_LOGGING, SID_INPUT }; if (setgroups(sizeof(groups) / sizeof(groups[0]), groups) != 0) { - D("set groups failed (errno: %d, %s)\n", errno, strerror(errno)); + D("set groups failed (errno: %d)\n", errno); } // then switch user and group to developer - if (setgid(GID_DEVELOPER) != 0) { - D("set group id failed (errno: %d, %s)\n", errno, strerror(errno)); + if (setgid(SID_DEVELOPER) != 0) { + D("set group id failed (errno: %d)\n", errno); return -1; } if (setuid(SID_DEVELOPER) != 0) { - D("set user id failed (errno: %d, %s)\n", errno, strerror(errno)); + D("set user id failed (errno: %d)\n", errno); return -1; } @@ -1139,6 +1404,226 @@ int set_developer_privileges() { } #define ONDEMAND_ROOT_PATH tzplatform_getenv(TZ_SDK_HOME) +static void execute_required_process() { + char *cmd_args[] = {"/usr/bin/debug_launchpad_preloading_preinitializing_daemon",NULL}; + + spawn("/usr/bin/debug_launchpad_preloading_preinitializing_daemon", cmd_args); +} + +/* default plugin proc */ +static int get_plugin_capability(const char* in_buf, sdbd_plugin_param out) { + int ret = SDBD_PLUGIN_RET_NOT_SUPPORT; + + if (in_buf == NULL) { + D("Invalid argument\n"); + return SDBD_PLUGIN_RET_FAIL; + } + + if (SDBD_CMP_CAP(in_buf, SECURE)) { + snprintf(out.data, out.len, "%s", SDBD_CAP_RET_DISABLED); + ret = SDBD_PLUGIN_RET_SUCCESS; + } else if (SDBD_CMP_CAP(in_buf, INTER_SHELL)) { + snprintf(out.data, out.len, "%s", SDBD_CAP_RET_ENABLED); + ret = SDBD_PLUGIN_RET_SUCCESS; + } else if (SDBD_CMP_CAP(in_buf, FILESYNC)) { + // - push : SDBD_CAP_RET_PUSH + // - pull : SDBD_CAP_RET_PULL + // - both : SDBD_CAP_RET_PUSHPULL + // - disabled : SDBD_CAP_RET_DISABLED + snprintf(out.data, out.len, "%s", SDBD_CAP_RET_PUSHPULL); + ret = SDBD_PLUGIN_RET_SUCCESS; + } else if (SDBD_CMP_CAP(in_buf, USBPROTO)) { + if (is_emulator()) { + snprintf(out.data, out.len, "%s", SDBD_CAP_RET_DISABLED); + } else { + snprintf(out.data, out.len, "%s", SDBD_CAP_RET_ENABLED); + } + ret = SDBD_PLUGIN_RET_SUCCESS; + } else if (SDBD_CMP_CAP(in_buf, SOCKPROTO)) { + if (is_emulator()) { + snprintf(out.data, out.len, "%s", SDBD_CAP_RET_ENABLED); + } else { + snprintf(out.data, out.len, "%s", SDBD_CAP_RET_ENABLED); + } + ret = SDBD_PLUGIN_RET_SUCCESS; + } else if (SDBD_CMP_CAP(in_buf, ROOTONOFF)) { + if (access("/bin/su", F_OK) == 0) { + snprintf(out.data, out.len, "%s", SDBD_CAP_RET_ENABLED); + } else { + snprintf(out.data, out.len, "%s", SDBD_CAP_RET_DISABLED); + } + } else if (SDBD_CMP_CAP(in_buf, PLUGIN_VER)) { + snprintf(out.data, out.len, "%s", UNKNOWN); + ret = SDBD_PLUGIN_RET_SUCCESS; + } else if (SDBD_CMP_CAP(in_buf, PRODUCT_VER)) { + snprintf(out.data, out.len, "%s", UNKNOWN); + ret = SDBD_PLUGIN_RET_SUCCESS; + } + + return ret; +} + +static int verify_shell_cmd(const char* in_buf, sdbd_plugin_param out) { + int ret = SDBD_PLUGIN_RET_FAIL; + + if (in_buf == NULL) { + D("Invalid argument\n"); + return SDBD_PLUGIN_RET_FAIL; + } + + D("shell command : %s\n", in_buf); + + snprintf(out.data, out.len, "%s", SDBD_RET_VALID); + ret = SDBD_PLUGIN_RET_SUCCESS; + + return ret; +} + +static int convert_shell_cmd(const char* in_buf, sdbd_plugin_param out) { + int ret = SDBD_PLUGIN_RET_FAIL; + + if (in_buf == NULL) { + D("Invalid argument\n"); + return SDBD_PLUGIN_RET_FAIL; + } + + snprintf(out.data, out.len, "%s", in_buf); + ret = SDBD_PLUGIN_RET_SUCCESS; + + return ret; +} + +static int verify_peer_ip(const char* in_buf, sdbd_plugin_param out) { + int ret = SDBD_PLUGIN_RET_FAIL; + + if (in_buf == NULL) { + D("Invalid argument\n"); + return SDBD_PLUGIN_RET_FAIL; + } + + D("peer ip : %s\n", in_buf); + + snprintf(out.data, out.len, "%s", SDBD_RET_VALID); + ret = SDBD_PLUGIN_RET_SUCCESS; + + return ret; +} + +static int verify_sdbd_launch(const char* in_buf, sdbd_plugin_param out) { + snprintf(out.data, out.len, "%s", SDBD_RET_VALID); + return SDBD_PLUGIN_RET_SUCCESS; +} + +static int verify_root_cmd(const char* in_buf, sdbd_plugin_param out) { + int ret = SDBD_PLUGIN_RET_FAIL; + + if (in_buf == NULL) { + D("Invalid argument\n"); + return SDBD_PLUGIN_RET_FAIL; + } + + D("shell command : %s\n", in_buf); + + if (verify_root_commands(in_buf)) { + snprintf(out.data, out.len, "%s", SDBD_RET_VALID); + } else { + snprintf(out.data, out.len, "%s", SDBD_RET_INVALID); + } + ret = SDBD_PLUGIN_RET_SUCCESS; + + return ret; +} + +int default_cmd_proc(const char* cmd, + const char* in_buf, sdbd_plugin_param out) { + int ret = SDBD_PLUGIN_RET_NOT_SUPPORT; + + /* Check the arguments */ + if (cmd == NULL || out.data == NULL) { + D("Invalid argument\n"); + return SDBD_PLUGIN_RET_FAIL; + } + + D("handle the command : %s\n", cmd); + + /* Handle the request from sdbd */ + if (SDBD_CMP_CMD(cmd, PLUGIN_CAP)) { + ret = get_plugin_capability(in_buf, out); + } else if (SDBD_CMP_CMD(cmd, VERIFY_SHELLCMD)) { + ret = verify_shell_cmd(in_buf, out); + } else if (SDBD_CMP_CMD(cmd, CONV_SHELLCMD)) { + ret = convert_shell_cmd(in_buf, out); + } else if (SDBD_CMP_CMD(cmd, VERIFY_PEERIP)) { + ret = verify_peer_ip(in_buf, out); + } else if (SDBD_CMP_CMD(cmd, VERIFY_LAUNCH)) { + ret = verify_sdbd_launch(in_buf, out); + } else if (SDBD_CMP_CMD(cmd, VERIFY_ROOTCMD)) { + ret = verify_root_cmd(in_buf, out); + } else { + D("Not supported command : %s\n", cmd); + ret = SDBD_PLUGIN_RET_NOT_SUPPORT; + } + + return ret; +} + +int request_plugin_cmd(const char* cmd, const char* in_buf, + char *out_buf, unsigned int out_len) +{ + int ret = SDBD_PLUGIN_RET_FAIL; + sdbd_plugin_param out; + + if (out_len > SDBD_PLUGIN_OUTBUF_MAX) { + D("invalid parameter : %s\n", cmd); + return 0; + } + + out.data = out_buf; + out.len = out_len; + + ret = sdbd_plugin_cmd_proc(cmd, in_buf, out); + if (ret == SDBD_PLUGIN_RET_FAIL) { + D("failed to request : %s\n", cmd); + return 0; + } + if (ret == SDBD_PLUGIN_RET_NOT_SUPPORT) { + // retry in default handler + ret = default_cmd_proc(cmd, in_buf, out); + if (ret == SDBD_PLUGIN_RET_FAIL) { + D("failed to request : %s\n", cmd); + return 0; + } + } + + // add null character. + out_buf[out_len-1] = '\0'; + D("return value: %s\n", out_buf); + + return 1; +} + +static void load_sdbd_plugin() { + sdbd_plugin_cmd_proc = NULL; + + g_sdbd_plugin_handle = dlopen(SDBD_PLUGIN_PATH, RTLD_NOW); + if (!g_sdbd_plugin_handle) { + D("failed to dlopen(%s). error: %s\n", SDBD_PLUGIN_PATH, dlerror()); + sdbd_plugin_cmd_proc = default_cmd_proc; + return; + } + + sdbd_plugin_cmd_proc = dlsym(g_sdbd_plugin_handle, SDBD_PLUGIN_INTF); + if (!sdbd_plugin_cmd_proc) { + D("failed to get the sdbd plugin interface. error: %s\n", dlerror()); + dlclose(g_sdbd_plugin_handle); + g_sdbd_plugin_handle = NULL; + sdbd_plugin_cmd_proc = default_cmd_proc; + return; + } + + D("using sdbd plugin interface.(%s)\n", SDBD_PLUGIN_PATH); +} + static void init_sdk_requirements() { struct stat st; @@ -1163,49 +1648,241 @@ static void init_sdk_requirements() { } } + execute_required_process(); + + register_pwlock_cb(); + + if (is_emulator()) { + register_bootdone_cb(); + } } #endif /* !SDB_HOST */ -static void get_plugin_capability(void) +int request_plugin_verification(const char* cmd, const char* in_buf) { + char out_buf[32] = {0,}; + + if(!request_plugin_cmd(cmd, in_buf, out_buf, sizeof(out_buf))) { + D("failed to request plugin command. : %s\n", SDBD_CMD_VERIFY_LAUNCH); + return 0; + } + + if (strlen(out_buf) == 7 && !strncmp(out_buf, SDBD_RET_INVALID, 7)) { + D("[%s] is NOT verified.\n", cmd); + return 0; + } + + D("[%s] is verified.\n", cmd); + return 1; +} + +static char* get_cpu_architecture() { - int len; - char *usb_state; - char *sock_state; + int ret = 0; + bool b_value = false; + + ret = system_info_get_platform_bool( + "http://tizen.org/feature/platform.core.cpu.arch.armv6", &b_value); + if (ret == SYSTEM_INFO_ERROR_NONE && b_value) { + return CPUARCH_ARMV6; + } + + ret = system_info_get_platform_bool( + "http://tizen.org/feature/platform.core.cpu.arch.armv7", &b_value); + if (ret == SYSTEM_INFO_ERROR_NONE && b_value) { + return CPUARCH_ARMV7; + } + + ret = system_info_get_platform_bool( + "http://tizen.org/feature/platform.core.cpu.arch.x86", &b_value); + if (ret == SYSTEM_INFO_ERROR_NONE && b_value) { + return CPUARCH_X86; + } + + D("fail to get the CPU architecture of model:%d\n", errno); + return UNKNOWN; +} + +static void init_capabilities(void) { + int ret = -1; + char *value = NULL; + + memset(&g_capabilities, 0, sizeof(g_capabilities)); + + // CPU Architecture of model + snprintf(g_capabilities.cpu_arch, sizeof(g_capabilities.cpu_arch), + "%s", get_cpu_architecture()); + + + // Secure protocol support + if(!request_plugin_cmd(SDBD_CMD_PLUGIN_CAP, SDBD_CAP_TYPE_SECURE, + g_capabilities.secure_protocol, + sizeof(g_capabilities.secure_protocol))) { + D("failed to request. (%s:%s) \n", SDBD_CMD_PLUGIN_CAP, SDBD_CAP_TYPE_SECURE); + snprintf(g_capabilities.secure_protocol, sizeof(g_capabilities.secure_protocol), + "%s", DISABLED); + } + + + // Interactive shell support + if(!request_plugin_cmd(SDBD_CMD_PLUGIN_CAP, SDBD_CAP_TYPE_INTER_SHELL, + g_capabilities.intershell_support, + sizeof(g_capabilities.intershell_support))) { + D("failed to request. (%s:%s) \n", SDBD_CMD_PLUGIN_CAP, SDBD_CAP_TYPE_INTER_SHELL); + snprintf(g_capabilities.intershell_support, sizeof(g_capabilities.intershell_support), + "%s", DISABLED); + } - if (is_emulator()) - usb_state = SDBD_CAP_RET_DISABLED; - else - usb_state = SDBD_CAP_RET_ENABLED; - sock_state = SDBD_CAP_RET_ENABLED; + // File push/pull support + if(!request_plugin_cmd(SDBD_CMD_PLUGIN_CAP, SDBD_CAP_TYPE_FILESYNC, + g_capabilities.filesync_support, + sizeof(g_capabilities.filesync_support))) { + D("failed to request. (%s:%s) \n", SDBD_CMD_PLUGIN_CAP, SDBD_CAP_TYPE_FILESYNC); + snprintf(g_capabilities.filesync_support, sizeof(g_capabilities.filesync_support), + "%s", DISABLED); + } + + + // USB protocol support + if(!request_plugin_cmd(SDBD_CMD_PLUGIN_CAP, SDBD_CAP_TYPE_USBPROTO, + g_capabilities.usbproto_support, + sizeof(g_capabilities.usbproto_support))) { + D("failed to request. (%s:%s) \n", SDBD_CMD_PLUGIN_CAP, SDBD_CAP_TYPE_USBPROTO); + snprintf(g_capabilities.usbproto_support, sizeof(g_capabilities.usbproto_support), + "%s", DISABLED); + } + + + // Socket protocol support + if(!request_plugin_cmd(SDBD_CMD_PLUGIN_CAP, SDBD_CAP_TYPE_SOCKPROTO, + g_capabilities.sockproto_support, + sizeof(g_capabilities.sockproto_support))) { + D("failed to request. (%s:%s) \n", SDBD_CMD_PLUGIN_CAP, SDBD_CAP_TYPE_SOCKPROTO); + snprintf(g_capabilities.sockproto_support, sizeof(g_capabilities.sockproto_support), + "%s", DISABLED); + } + + + // Root command support + if(!request_plugin_cmd(SDBD_CMD_PLUGIN_CAP, SDBD_CAP_TYPE_ROOTONOFF, + g_capabilities.rootonoff_support, + sizeof(g_capabilities.rootonoff_support))) { + D("failed to request. (%s:%s) \n", SDBD_CMD_PLUGIN_CAP, SDBD_CAP_TYPE_ROOTONOFF); + snprintf(g_capabilities.rootonoff_support, sizeof(g_capabilities.rootonoff_support), + "%s", DISABLED); + } + + + // Zone support + ret = is_container_enabled(); + snprintf(g_capabilities.zone_support, sizeof(g_capabilities.zone_support), + "%s", ret == 1 ? ENABLED : DISABLED); + + + // Multi-User support + // TODO: get this information from platform. + snprintf(g_capabilities.multiuser_support, sizeof(g_capabilities.multiuser_support), + "%s", DISABLED); + + + // Window size synchronization support + snprintf(g_capabilities.syncwinsz_support, sizeof(g_capabilities.syncwinsz_support), + "%s", ENABLED); + + + // Profile name + ret = system_info_get_platform_string("http://tizen.org/feature/profile", &value); + if (ret != SYSTEM_INFO_ERROR_NONE) { + snprintf(g_capabilities.profile_name, sizeof(g_capabilities.profile_name), + "%s", UNKNOWN); + D("fail to get profile name:%d\n", errno); + } else { + snprintf(g_capabilities.profile_name, sizeof(g_capabilities.profile_name), + "%s", value); + if (value != NULL) { + free(value); + } + } + + + // Vendor name + ret = system_info_get_platform_string("http://tizen.org/system/manufacturer", &value); + if (ret != SYSTEM_INFO_ERROR_NONE) { + snprintf(g_capabilities.vendor_name, sizeof(g_capabilities.vendor_name), + "%s", UNKNOWN); + D("fail to get the Vendor name:%d\n", errno); + } else { + snprintf(g_capabilities.vendor_name, sizeof(g_capabilities.vendor_name), + "%s", value); + if (value != NULL) { + free(value); + } + } + + + // Platform version + ret = system_info_get_platform_string("http://tizen.org/feature/platform.version", &value); + if (ret != SYSTEM_INFO_ERROR_NONE) { + snprintf(g_capabilities.platform_version, sizeof(g_capabilities.platform_version), + "%s", UNKNOWN); + D("fail to get platform version:%d\n", errno); + } else { + snprintf(g_capabilities.platform_version, sizeof(g_capabilities.platform_version), + "%s", value); + if (value != NULL) { + free(value); + } + } - len = sizeof(g_capabilities.usbproto_support); - snprintf(g_capabilities.usbproto_support, len, - "%s", usb_state); - len = sizeof(g_capabilities.sockproto_support); - snprintf(g_capabilities.sockproto_support, len, - "%s", sock_state); + // Product version + if(!request_plugin_cmd(SDBD_CMD_PLUGIN_CAP, SDBD_CAP_TYPE_PRODUCT_VER, + g_capabilities.product_version, + sizeof(g_capabilities.product_version))) { + D("failed to request. (%s:%s) \n", SDBD_CMD_PLUGIN_CAP, SDBD_CAP_TYPE_PRODUCT_VER); + snprintf(g_capabilities.product_version, sizeof(g_capabilities.product_version), + "%s", UNKNOWN); + } + + + // Sdbd version + snprintf(g_capabilities.sdbd_version, sizeof(g_capabilities.sdbd_version), + "%d.%d.%d", SDB_VERSION_MAJOR, SDB_VERSION_MINOR, SDB_VERSION_PATCH); + + + // Sdbd plugin version + if(!request_plugin_cmd(SDBD_CMD_PLUGIN_CAP, SDBD_CAP_TYPE_PLUGIN_VER, + g_capabilities.sdbd_plugin_version, + sizeof(g_capabilities.sdbd_plugin_version))) { + D("failed to request. (%s:%s) \n", SDBD_CMD_PLUGIN_CAP, SDBD_CAP_TYPE_PLUGIN_VER); + snprintf(g_capabilities.sdbd_plugin_version, sizeof(g_capabilities.sdbd_plugin_version), + "%s", UNKNOWN); + } } static int is_support_usbproto() { - return (!strncmp(g_capabilities.usbproto_support, - SDBD_CAP_RET_ENABLED, strlen(SDBD_CAP_RET_ENABLED))); + return (!strncmp(g_capabilities.usbproto_support, SDBD_CAP_RET_ENABLED, strlen(SDBD_CAP_RET_ENABLED))); } static int is_support_sockproto() { - return (!strncmp(g_capabilities.sockproto_support, - SDBD_CAP_RET_ENABLED, strlen(SDBD_CAP_RET_ENABLED))); + return (!strncmp(g_capabilities.sockproto_support, SDBD_CAP_RET_ENABLED, strlen(SDBD_CAP_RET_ENABLED))); } int sdb_main(int is_daemon, int server_port) { #if !SDB_HOST - get_plugin_capability(); + load_sdbd_plugin(); + init_capabilities(); + init_drop_privileges(); init_sdk_requirements(); + if (!request_plugin_verification(SDBD_CMD_VERIFY_LAUNCH, NULL)) { + D("sdbd should be launched in develop mode.\n"); + return -1; + } + umask(000); #endif @@ -1276,37 +1953,38 @@ int sdb_main(int is_daemon, int server_port) } } - if (is_support_usbproto()) { - if (!is_emulator()) { - /* choose the usb gadget backend */ - if (access(USB_NODE_FILE, F_OK) == 0) { - /* legacy kernel-based sdb gadget */ - usb_init = &linux_usb_init; - usb_cleanup = &linux_usb_cleanup; - usb_write = &linux_usb_write; - usb_read = &linux_usb_read; - usb_close = &linux_usb_close; - usb_kick = &linux_usb_kick; - } else { - /* functionfs based gadget */ - usb_init = &ffs_usb_init; - usb_cleanup = &ffs_usb_cleanup; - usb_write = &ffs_usb_write; - usb_read = &ffs_usb_read; - usb_close = &ffs_usb_close; - usb_kick = &ffs_usb_kick; - } - // listen on USB - usb_init(); - } - } + if (is_support_usbproto()) { + /* choose the usb gadget backend */ + if (access(USB_NODE_FILE, F_OK) == 0) { + /* legacy kernel-based sdb gadget */ + usb_init = &linux_usb_init; + usb_cleanup = &linux_usb_cleanup; + usb_write = &linux_usb_write; + usb_read = &linux_usb_read; + usb_close = &linux_usb_close; + usb_kick = &linux_usb_kick; + } else { + /* functionfs based gadget */ + usb_init = &ffs_usb_init; + usb_cleanup = &ffs_usb_cleanup; + usb_write = &ffs_usb_write; + usb_read = &ffs_usb_read; + usb_close = &ffs_usb_close; + usb_kick = &ffs_usb_kick; + } - if (is_support_sockproto()) { - /* by default don't listen on local transport but - * listen if suitable command line argument has been provided */ - if (sdbd_commandline_args.sdbd_port >= 0) - local_init(sdbd_commandline_args.sdbd_port); - } + // listen on USB + usb_init(); + } + if (is_support_sockproto()) { + /* by default don't listen on local transport but + * listen if suitable command line argument has been provided */ + if (sdbd_commandline_args.sdbd_port >= 0) { + local_init(sdbd_commandline_args.sdbd_port); + } else { + local_init(DEFAULT_SDB_LOCAL_TRANSPORT_PORT); + } + } #if 0 /* tizen specific */ D("sdb_main(): pre init_jdwp()\n"); @@ -1344,7 +2022,7 @@ void connect_device(char* host, char* buffer, int buffer_size) char hostbuf[100]; char serial[100]; - strncpy(hostbuf, host, sizeof(hostbuf) - 1); + s_strncpy(hostbuf, host, sizeof(hostbuf) - 1); if (portstr) { if (portstr - host >= sizeof(hostbuf)) { snprintf(buffer, buffer_size, "bad host name %s", host); @@ -1435,6 +2113,31 @@ void connect_emulator(char* port_spec, char* buffer, int buffer_size) } #endif +int copy_packet(apacket* dest, apacket* src) { + + if(dest == NULL) { + D("dest packet is NULL\n"); + return -1; + } + + if(src == NULL) { + D("src packet is NULL\n"); + return -1; + } + + dest->next = src->next; + dest->ptr = src->ptr; + dest->len = src->len; + + int data_length = src->msg.data_length; + if(data_length > MAX_PAYLOAD) { + data_length = MAX_PAYLOAD; + } + memcpy(&(dest->msg), &(src->msg), sizeof(amessage) + data_length); + + return 0; +} + int handle_host_request(char *service, transport_type ttype, char* serial, int reply_fd, asocket *s) { atransport *transport = NULL; @@ -1671,7 +2374,7 @@ int main(int argc, char **argv) #if !SDB_HOST if (daemonize() < 0) - fatal("daemonize() failed: %.200s", strerror(errno)); + fatal("daemonize() failed: errno:%d", errno); #endif start_device_log(); diff --git a/src/sdb.h b/src/sdb.h index da25ab1..9cef525 100644 --- a/src/sdb.h +++ b/src/sdb.h @@ -19,9 +19,11 @@ #include #include +#include #include "transport.h" /* readx(), writex() */ #include "fdevent.h" +#include "sdbd_plugin.h" #if !SDB_HOST #include "commandline_sdbd.h" #endif @@ -35,11 +37,13 @@ #define A_OKAY 0x59414b4f #define A_CLSE 0x45534c43 #define A_WRTE 0x45545257 +#define A_STAT 0x54415453 -#define A_VERSION 0x01000000 // SDB protocol version +#define A_VERSION 0x02000000 // SDB protocol version #define SDB_VERSION_MAJOR 2 // Used for help/version information -#define SDB_VERSION_MINOR 1 // Used for help/version information +#define SDB_VERSION_MINOR 2 // Used for help/version information +#define SDB_VERSION_PATCH 31 // Used for help/version information #define SDB_SERVER_VERSION 0 // Increment this when we want to force users to start a new sdb server @@ -92,11 +96,6 @@ struct asocket { */ int closing; - /* flag: quit adbd when both ends close the - ** local service socket - */ - int exit_on_close; - /* the asocket we are connected to */ @@ -228,16 +227,54 @@ struct alistener adisconnect disconnect; }; -#define SDBD_CAP_RET_ENABLED "enabled" -#define SDBD_CAP_RET_DISABLED "disabled" +#define UNKNOWN "unknown" +#define INFOBUF_MAXLEN 64 +#define INFO_VERSION "2.2.0" +typedef struct platform_info { + char platform_info_version[INFOBUF_MAXLEN]; + char model_name[INFOBUF_MAXLEN]; // Emulator + char platform_name[INFOBUF_MAXLEN]; // Tizen + char platform_version[INFOBUF_MAXLEN]; // 2.2.1 + char profile_name[INFOBUF_MAXLEN]; // 2.2.1 +} pinfo; + +#define ENABLED "enabled" +#define DISABLED "disabled" +#define CPUARCH_ARMV6 "armv6" +#define CPUARCH_ARMV7 "armv7" +#define CPUARCH_X86 "x86" +#define CAPBUF_SIZE 4096 #define CAPBUF_ITEMSIZE 32 typedef struct platform_capabilities { - char usbproto_support[CAPBUF_ITEMSIZE]; // enabled or disabled - char sockproto_support[CAPBUF_ITEMSIZE]; // enabled or disabled + char secure_protocol[CAPBUF_ITEMSIZE]; // enabled or disabled + char intershell_support[CAPBUF_ITEMSIZE]; // enabled or disabled + char filesync_support[CAPBUF_ITEMSIZE]; // push or pull or pushpull or disabled + char rootonoff_support[CAPBUF_ITEMSIZE]; // enabled or disabled + char zone_support[CAPBUF_ITEMSIZE]; // enabled or disabled + char multiuser_support[CAPBUF_ITEMSIZE]; // enabled or disabled + char syncwinsz_support[CAPBUF_ITEMSIZE]; // enabled or disabled + char usbproto_support[CAPBUF_ITEMSIZE]; // enabled or disabled + char sockproto_support[CAPBUF_ITEMSIZE]; // enabled or disabled + + char cpu_arch[CAPBUF_ITEMSIZE]; // cpu architecture (ex. x86) + char profile_name[CAPBUF_ITEMSIZE]; // profile name (ex. mobile) + char vendor_name[CAPBUF_ITEMSIZE]; // vendor name (ex. Tizen) + + char platform_version[CAPBUF_ITEMSIZE]; // platform version (ex. 2.3.0) + char product_version[CAPBUF_ITEMSIZE]; // product version (ex. 1.0) + char sdbd_version[CAPBUF_ITEMSIZE]; // sdbd version + char sdbd_plugin_version[CAPBUF_ITEMSIZE]; // sdbd plugin version } pcap; pcap g_capabilities; +#define SDBD_PLUGIN_PATH "/usr/lib/libsdbd_plugin.so" +#define SDBD_PLUGIN_INTF "sdbd_plugin_cmd_proc" +typedef int (*SDBD_PLUGIN_CMD_PROC_PTR)(const char*, const char*, sdbd_plugin_param); +extern SDBD_PLUGIN_CMD_PROC_PTR sdbd_plugin_cmd_proc; +int request_plugin_cmd(const char* cmd, const char* in_buf, char *out_buf, unsigned int out_len); +int request_plugin_verification(const char* cmd, const char* in_buf); + void print_packet(const char *label, apacket *p); asocket *find_local_socket(unsigned id); @@ -271,6 +308,7 @@ int sdb_main(int is_daemon, int server_port); void init_transport_registration(void); int list_transports(char *buf, size_t bufsize); void update_transports(void); +void broadcast_transport(apacket *p); asocket* create_device_tracker(void); @@ -335,7 +373,8 @@ void log_service(int fd, void *cookie); void remount_service(int fd, void *cookie); char * get_log_file_path(const char * log_name); -int rootshell_mode;// 0: developer, 1: root +int rootshell_mode; // 0: developer, 1: root +int booting_done; // 0: platform booting is in progess 1: platform booting is done // This is the users and groups config for the platform @@ -350,6 +389,7 @@ int rootshell_mode;// 0: developer, 1: root #endif +int is_pwlocked(void); int should_drop_privileges(void); int set_developer_privileges(); void set_root_privileges(); @@ -357,6 +397,9 @@ void set_root_privileges(); int get_emulator_forward_port(void); int get_emulator_name(char str[], int str_size); int get_device_name(char str[], int str_size); +int get_emulator_hostip(char str[], int str_size); +int get_emulator_guestip(char str[], int str_size); + /* packet allocator */ apacket *get_apacket(void); void put_apacket(apacket *p); @@ -500,7 +543,7 @@ void ffs_usb_kick(usb_handle *h); void linux_usb_init(); void linux_usb_cleanup(); int linux_usb_write(usb_handle *h, const void *data, int len); -int linux_usb_read(usb_handle *h, void *data, int len); +int linux_usb_read(usb_handle *h, void *data, unsigned len); int linux_usb_close(usb_handle *h); void linux_usb_kick(usb_handle *h); @@ -524,6 +567,7 @@ int connection_state(atransport *t); #define CS_RECOVERY 4 #define CS_NOPERM 5 /* Insufficient permissions to communicate with the device */ #define CS_SIDELOAD 6 +#define CS_PWLOCK 10 extern int HOST; extern int SHELL_EXIT_NOTIFY_FD; @@ -535,6 +579,7 @@ extern SdbdCommandlineArgs sdbd_commandline_args; int sendfailmsg(int fd, const char *reason); int handle_host_request(char *service, transport_type ttype, char* serial, int reply_fd, asocket *s); +int copy_packet(apacket* dest, apacket* src); int is_emulator(void); #define DEFAULT_DEVICENAME "unknown" diff --git a/src/sdbd_plugin.h b/src/sdbd_plugin.h new file mode 100644 index 0000000..81c590a --- /dev/null +++ b/src/sdbd_plugin.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __SDBD_PLUGIN_H +#define __SDBD_PLUGIN_H + +#include + +/* plugin commands */ +#define SDBD_CMD_PLUGIN_CAP "plugin_capability" +#define SDBD_CMD_VERIFY_SHELLCMD "verify_shell_cmd" +#define SDBD_CMD_CONV_SHELLCMD "convert_shell_cmd" +#define SDBD_CMD_VERIFY_PEERIP "verify_peer_ip" +#define SDBD_CMD_VERIFY_LAUNCH "verify_sdbd_launch" +#define SDBD_CMD_VERIFY_ROOTCMD "verify_root_cmd" + +/* plugin capabilities */ +#define SDBD_CAP_TYPE_SECURE "secure_protocol_support" +#define SDBD_CAP_TYPE_INTER_SHELL "interactive_shell_support" +#define SDBD_CAP_TYPE_FILESYNC "file_sync_support" +#define SDBD_CAP_TYPE_USBPROTO "usb_protocol_support" +#define SDBD_CAP_TYPE_SOCKPROTO "socket_protocol_support" +#define SDBD_CAP_TYPE_ROOTONOFF "root_onoff_support" +#define SDBD_CAP_TYPE_PLUGIN_VER "sdbd_plugin_version" +#define SDBD_CAP_TYPE_PRODUCT_VER "product_version" +/* capability return string */ +#define SDBD_CAP_RET_ENABLED "enabled" +#define SDBD_CAP_RET_DISABLED "disabled" +#define SDBD_CAP_RET_PUSH "push" +#define SDBD_CAP_RET_PULL "pull" +#define SDBD_CAP_RET_PUSHPULL "pushpull" + +/* verification return string */ +#define SDBD_RET_VALID "valid" +#define SDBD_RET_INVALID "invalid" + +/* proc interface return value */ +#define SDBD_PLUGIN_RET_SUCCESS (0) +#define SDBD_PLUGIN_RET_FAIL (-1) +#define SDBD_PLUGIN_RET_NOT_SUPPORT (-2) + +/* utility macro */ +#define SDBD_CMP_CMD(cmd, type) \ + ((strlen(cmd) == strlen(SDBD_CMD_##type) \ + && !strncmp(cmd, SDBD_CMD_##type, strlen(cmd)))?1:0) + +#define SDBD_CMP_CAP(cap, type) \ + ((strlen(cap) == (strlen(SDBD_CAP_TYPE_##type)) \ + && !strncmp(cap, SDBD_CAP_TYPE_##type, strlen(cap)))?1:0) + +/* out parameter structure */ +#define SDBD_SHELL_CMD_MAX 4096 +#define SDBD_PLUGIN_OUTBUF_MAX 4096 +typedef struct sdbd_plugin_param { + unsigned int len; + char *data; +} sdbd_plugin_param; + +/* log system */ +// 1. set the environment value. : SDB_TRACE=all +// 2. restart the sdbd deamon. +// 3. log is output to the /tmp/sdbd-[date].txt +#define SDBD_PLUGIN_LOG(...) \ + fprintf(stderr, "%s::%s():", \ + __FILE__, __FUNCTION__); \ + fprintf(stderr, __VA_ARGS__); + +#endif diff --git a/src/sdktools.c b/src/sdktools.c index d1cd388..814e066 100644 --- a/src/sdktools.c +++ b/src/sdktools.c @@ -16,47 +16,116 @@ #include "sdktools.h" #include "strutils.h" #include "fileutils.h" +#include "utils.h" struct sudo_command root_commands[] = { - /* 0 */ {"killall", "/usr/bin/killall"}, - /* 1 */ {"zypper", "/usr/bin/zypper"}, - /* 2 */ {"da_command", "/usr/bin/da_command"}, - /* 3 */ {"oprofile", "/usr/bin/oprofile_command"}, - /* end */ {NULL, NULL} + /* 0 */ + { "profile", "/usr/bin/profile_command", + { "killmanager", + "runmanager", + "findunittest", + "process", + "getversion", + "killvalgrind", + "getprobemap", + NULL + } + }, + /* end */ + { NULL, NULL, NULL } }; -struct arg_permit_rule sdk_arg_permit_rule[] = { - /* 2 */ {"gcove_env1", "^GCOV_PREFIX=((/opt/apps)|(/opt/usr/apps))/[a-zA-Z0-9]{10}/data$", 1}, - /* 2 */ {"gcove_env2", "GCOV_PREFIX_STRIP=0", 0}, - /* 2 */ {"gcove_env3", "LD_LIBRARY_PATH=/home/developer/sdk_tools/gtest/usr/lib:$LD_LIBRARY_PATH", 0}, - /* 2 */ {"gcove_env4", "TIZEN_LAUNCH_MODE=debug", 0}, - /* 2 */ {"da_env1", "LD_PRELOAD=/usr/lib/da_probe_osp.so", 0}, - /* 2 */ {"gcove_arg1", "^\\-\\-gtest_output=xml:((/opt/apps)|(/opt/usr/apps))/[a-zA-Z0-9]{10}/data/[a-zA-Z0-9_\\-]{1,30}\\.xml$", 1}, - /* end */ {NULL, NULL, 0} +static struct command_suffix +{ + const char *name; // comments for human + const char *suffix; //pattern }; -void init_sdk_arg_permit_rule_pattern(void) -{ - asprintf(&sdk_arg_permit_rule[0].pattern, "^GCOV_PREFIX=((%s)|(%s))/[a-zA-Z0-9]{10}/data$", APP_INSTALL_PATH_PREFIX1, APP_INSTALL_PATH_PREFIX2); - asprintf(&sdk_arg_permit_rule[1].pattern, "GCOV_PREFIX_STRIP=0"); - asprintf(&sdk_arg_permit_rule[2].pattern, "LD_LIBRARY_PATH=%s/gtest/usr/lib:$LD_LIBRARY_PATH", DEV_INSTALL_PATH_PREFIX, APP_INSTALL_PATH_PREFIX2); - asprintf(&sdk_arg_permit_rule[3].pattern, "TIZEN_LAUNCH_MODE=debug"); - asprintf(&sdk_arg_permit_rule[4].pattern, "LD_PRELOAD=/usr/lib/da_probe_osp.so", DEV_INSTALL_PATH_PREFIX, APP_INSTALL_PATH_PREFIX2); - asprintf(&sdk_arg_permit_rule[5].pattern, "^\\-\\-gtest_output=xml:((%s)|(%s))/[a-zA-Z0-9]{10}/data/[a-zA-Z0-9_\\-]{1,30}\\.xml$", APP_INSTALL_PATH_PREFIX1, APP_INSTALL_PATH_PREFIX2); -} +static struct command_suffix CMD_SUFFIX_DENY_KEYWORD[] = { + /* 0 */ {"pipe", "|"}, + /* 1 */ {"redirect", ">"}, + /* 2 */ {"semicolon", ";"}, // separated list is executed + /* 3 */ {"and", "&"}, + /* 4 */ {"command_substitution1", "$"}, + /* 5 */ {"command_substitution2", "`"}, + /* end */ {NULL, NULL} +}; +/** + * return 1 if the arg is arrowed, otherwise 0 is denied + */ +static int is_cmd_suffix_denied(const char* arg) { + int i; -int verify_commands(const char *arg1) { - if (arg1 != NULL) { - if (verify_root_commands(arg1)) { - // do not drop privilege only if root auth is required + for (i=0; CMD_SUFFIX_DENY_KEYWORD[i].name != NULL; i++) { + if (strstr(arg, CMD_SUFFIX_DENY_KEYWORD[i].suffix) != NULL) { + D("cmd suffix denied:%s\n", arg); return 1; } } - // doing these steps if we don't have root permission - if (should_drop_privileges()) { - set_developer_privileges(); + D("cmd suffix arrowed:%s\n", arg); + return 0; +} + +static int get_application_install_path(char* pkg_path) { + FILE *fp = NULL; + char ret_str[PATH_MAX+64] = {0,}; + int len = 0; + + fp = popen("/usr/bin/pkgcmd -a", "r"); + if (fp == NULL) { + D("failed : popen pkgcmd -a\n"); + return 0; } + if (!fgets(ret_str, PATH_MAX+64, fp)) { + D("failed : fgets pkgcmd -a\n"); + pclose(fp); + return 0; + } + pclose(fp); + + len = strlen(ret_str); + while(ret_str[--len]=='\n'); + ret_str[len + 1] = '\0'; + + if (sscanf(ret_str, "Tizen Application Installation Path: %s", pkg_path) != 1) { + D("failed : parsing fail (str:%s)\n", ret_str); + return 0; + } + + D("Tizen install path: %s\n", pkg_path); + return 1; +} + +int is_pkg_file_path(const char* path) { + regex_t regex; + int ret; + char pkg_path[PATH_MAX] = {0,}; + char pkg_path_regx[PATH_MAX+64] = {0,}; + + if (!get_application_install_path(pkg_path)) { + D("failed to get application install path\n"); + return 0; + } + + snprintf(pkg_path_regx, sizeof(pkg_path_regx), + "^.*(%s/tmp/)+[a-zA-Z0-9_\\-\\.]*\\.(wgt|tpk),*[0-9]*$", pkg_path); + + ret = regcomp(®ex, pkg_path_regx, REG_EXTENDED); + if (ret){ + D("failed : recomp (error:%d)\n", ret); + return 0; + } + + ret = regexec(®ex, path, 0, NULL, 0); + regfree(®ex); + + if (ret){ + D("This path is NOT package file: %s\n", path); + return 0; + } + + D("This path is temporary package file: %s\n", path); return 1; } @@ -81,54 +150,27 @@ int verify_root_commands(const char *arg1) { } index = is_root_commands(tokens[0]); if (index == -1) { - if (exec_app_standalone(arg1)) { - ret = 1; - } else { - return 0; // just keep going to execute normal commands - } + return 0; // just keep going to execute normal commands } switch (index) { + // in case of profile_command case 0: { - if (cnt == 2) { - if (verify_app_path(tokens[1])) { - ret = 1; - } - } - break; - } - case 1: { - ret = 1; - break; - } - case 2: { - ret = 1; - break; - } - case 3: { - if (!strcmp(tokens[1], "valgrind") && cnt >= 3) { - char *appid = NULL; - // the tokens[2] should be apppath - int rc = smack_lgetlabel(tokens[2], &appid, SMACK_LABEL_ACCESS); - if (rc == 0 && appid != NULL) { - if (apply_sdb_rules(SDBD_LABEL_NAME, appid, "rwax") < 0) { - D("unable to set %s %s rules\n", SDBD_LABEL_NAME, appid); - } else { - D("apply rule to '%s %s rwax' rules\n", SDBD_LABEL_NAME, appid); + ret = 0; + if (!is_cmd_suffix_denied(arg1) && (cnt == 2)) { + // check if command is used with permitted arguments + for (i = 0; root_commands[0].arguments[i] != NULL; i++) { + if (!strncmp(tokens[1], root_commands[0].arguments[i], strlen(tokens[1]))){ + D("found permitted arguments :%s\n", tokens[1]); + ret = 1; + break; } - if (apply_sdb_rules(appid, SDBD_LABEL_NAME, "rwax") < 0) { - D("unable to set %s %s rules\n", appid, SDBD_LABEL_NAME); - } else { - D("apply rule to '%s %s rwax' rules\n", appid, SDBD_LABEL_NAME); - } - //apply_app_process(); - free(appid); } - D("standalone launch for valgrind\n"); + if (ret == 0) { + D("not found permitted arguments :%s\n", tokens[1]); + } } - - ret = 1; break; } default: { @@ -145,15 +187,6 @@ int verify_root_commands(const char *arg1) { return ret; } -int verify_app_path(const char* path) { - char buf[PATH_MAX]; - - snprintf(buf, sizeof buf, "^((%s)|(%s))/[a-zA-Z0-9]{%d}/bin/[a-zA-Z0-9_\\-]{1,}(\\.exe)?$", APP_INSTALL_PATH_PREFIX1, APP_INSTALL_PATH_PREFIX2, 10); - int reg_cmp = regcmp(buf, path); - - return reg_cmp; -} - int regcmp(const char* pattern, const char* str) { regex_t regex; int ret; @@ -178,326 +211,6 @@ int regcmp(const char* pattern, const char* str) { return 0; } -int env_verify(const char* arg) { - int i; - init_sdk_arg_permit_rule_pattern(); - for (i=0; sdk_arg_permit_rule[i].name != NULL; i++) { - if (sdk_arg_permit_rule[i].expression == 0) { - if (!strcmp(sdk_arg_permit_rule[i].pattern, arg)) { - D("success to set %s\n", arg); - return 1; - } - } else if (sdk_arg_permit_rule[i].expression == 1) { - if (regcmp(sdk_arg_permit_rule[i].pattern, arg)) { - D("success to set %s\n", arg); - return 1; - } - } - } - D("failed to set %s\n", arg); - for (i = 0; i <= 6; i++){ - free(sdk_arg_permit_rule[i].pattern); - } - return 0; -} - -int exec_app_standalone(const char* path) { - char *tokens[MAX_TOKENS]; - int ret = 0; - int cnt = 0; - int flag = 1; - int i=0; - - cnt = tokenize(path, " ", tokens, MAX_TOKENS); - for (i=0; i=cnt) break; - if (env_verify(tokens[i])) { - flag = 1; - } - i++; - if (i>=cnt) break; - if (!strcmp("&&", tokens[i])) { - continue; - } - } - if (flag == 0) { - // TODO: check evn setting - } - - if(!strcmp(tokens[i], SDK_LAUNCH_PATH)) { - int debug = 0; - int pid = 0; - char* pkg_id = NULL; - char* executable = NULL; - ++i; - while( i < cnt ) { - if(!strcmp(tokens[i], "-attach")) { - if(++i < cnt) { - char* pid_pattern = "[1-9][0-9]{2,5}"; - if (regcmp(pid_pattern, tokens[i])) { - pid = atoi(tokens[i]); - } - } - } - else if(!strcmp(tokens[i], "-p")) { - if(++i < cnt) { - pkg_id = tokens[i]; - } - } - else if(!strcmp(tokens[i], "-e")) { - if(++i < cnt) { - executable = tokens[i]; - } - } - i++; - } - if(pid > 0) { - char cmdline[128]; - if (pid) { - snprintf(cmdline, sizeof(cmdline), "/proc/%d/cmdline", pid); - int fd = unix_open(cmdline, O_RDONLY); - if (fd > 0) { - if(read_line(fd, cmdline, sizeof(cmdline))) { - if (set_smack_rules_for_gdbserver(cmdline, 1)) { - ret = 1; - } - } - sdb_close(fd); - } - } - } - break; - } - // TODO: i length check - else if (!strcmp(tokens[i], GDBSERVER_PATH) || !strcmp(tokens[i], GDBSERVER_PLATFORM_PATH)) { //gdbserver :11 --attach 2332 (cnt=4,) - char *gdb_attach_arg_pattern = "^:[1-9][0-9]{2,5} \\-\\-attach [1-9][0-9]{2,5}$"; - int argcnt = cnt-i-1; - if (argcnt == 3 && !strcmp("--attach", tokens[i+2])) { - char cmdline[128]; - int pid = 0; - D("parsing.... debug attach mode\n"); - snprintf(cmdline, sizeof(cmdline), "%s %s %s",tokens[i+1], tokens[i+2], tokens[i+3]); - if (regcmp(gdb_attach_arg_pattern, cmdline)) { - char cmdline[128]; - pid = atoi(tokens[i+3]); - if (pid) { - snprintf(cmdline, sizeof(cmdline), "/proc/%d/cmdline", pid); - int fd = unix_open(cmdline, O_RDONLY); - if (fd > 0) { - if(read_line(fd, cmdline, sizeof(cmdline))) { - if (set_smack_rules_for_gdbserver(cmdline, 1)) { - ret = 1; - } - } - sdb_close(fd); - } - } - } - } - else if (argcnt >= 2) { - if(should_drop_privileges() == 0 || verify_app_path(tokens[i+2])) { - D("parsing.... debug run as mode\n"); - if (set_smack_rules_for_gdbserver(tokens[i+2], 0)) { - ret = 1; - } - } - } - D("finished debug launch mode\n"); - } else { - if (verify_app_path(tokens[i])) { - char *path = tokens[i]; - char *appid = NULL; - int rc = smack_lgetlabel(path, &appid, SMACK_LABEL_ACCESS); - if (rc == 0 && appid != NULL) { - if (apply_sdb_rules(SDBD_LABEL_NAME, appid, "rwax") < 0) { - D("unable to set sdbd rules to %s %s rwax\n", SDBD_LABEL_NAME, appid); - } else { - D("set sdbd rules to %s %s rwax\n", SDBD_LABEL_NAME, appid); - } - if (apply_sdb_rules(appid, SDBD_LABEL_NAME, "rwax") < 0) { - D("unable to set sdbd rules to %s %s rwax\n", appid, SDBD_LABEL_NAME); - } else { - D("set sdbd rules to %s %s rwax\n", appid, SDBD_LABEL_NAME); - } - if (smack_set_label_for_self(appid) != -1) { - D("set smack lebel [%s] appid to %s\n", appid, SMACK_LEBEL_SUBJECT_PATH); - apply_app_process(); - ret = 1; - } else { - D("unable to open %s due to %s\n", SMACK_LEBEL_SUBJECT_PATH, strerror(errno)); - } - free(appid); - } - D("standalone launch\n"); - } - } - // TODO: verify arguments - break; - } - - if (cnt) { - free_strings(tokens, cnt); - } - return ret; -} - -/** - * free after use it - */ -char* clone_gdbserver_label_from_app(const char* app_path) { - char *new_appid = NULL; - char appid[APPID_MAX_LENGTH+1] = {0, }; - char *buffer = NULL; - -#if 0 - if (!verify_app_path(app_path)) { - D("not be able to access %s\n", app_path); - return NULL; - } -#endif - - int rc = smack_lgetlabel(app_path, &buffer, SMACK_LABEL_ACCESS); - - if (rc == 0 && buffer != NULL) { - strncpy(appid, buffer, sizeof(appid) - 1); - free(buffer); - } else { - strncpy(appid, "_", sizeof(appid) - 1); - } - new_appid = (char *)malloc(sizeof(appid)+1); - strncpy(new_appid, appid, APPID_MAX_LENGTH); - // Do not label to gdbserver executable -/* - if (new_appid != NULL) { - rc = smack_lsetlabel(GDBSERVER_PATH, new_appid, SMACK_LABEL_ACCESS); - if (rc < 0) { - D("unable to set access smack label: %s to %s\n", GDBSERVER_PATH, new_appid); - } - D("set access smack label: %s to %s\n", GDBSERVER_PATH, new_appid); - - rc = smack_lsetlabel(GDBSERVER_PATH, new_appid, SMACK_LABEL_EXEC); - if (rc < 0) { - D("unable to set execute smack label: %s to %s\n", GDBSERVER_PATH, new_appid); - } - D("set execute smack label: %s to %s\n", GDBSERVER_PATH, new_appid); - } -*/ - return new_appid; -} - -int set_smack_rules_for_gdbserver(const char* apppath, int mode) { - // FIXME: set gdbfolder to 755 also - if(sdb_chmod(GDBSERVER_PATH, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH, 1) < 0) - { - D("unable to set 755 to %s", GDBSERVER_PATH); - } - - // in case of debug as mode - char *new_appid = clone_gdbserver_label_from_app(apppath); - if (new_appid != NULL) { - if (apply_sdb_rules(SDBD_LABEL_NAME, new_appid, "w") < 0) { - D("unable to set sdbd rules\n"); - } - if (apply_sdb_rules(new_appid, SDK_HOME_LABEL_NAME, "rx") < 0) { - D("unable to set sdbd home rules\n"); - } - if (smack_set_label_for_self(new_appid) != -1) { - D("set smack lebel [%s] appid to %s\n", new_appid, SMACK_LEBEL_SUBJECT_PATH); - // apply app precess only if not attach mode - if (mode == 0) { - apply_app_process(); - } - } else { - D("unable to open %s due to %s\n", SMACK_LEBEL_SUBJECT_PATH, strerror(errno)); - } - free(new_appid); - return 1; - } - // TODO: in case of attach mode - return 0; -} - -int apply_sdb_rules(const char* subject, const char* object, const char* access_type) { - struct smack_accesses *rules = NULL; - int ret = 0; - - if (smack_accesses_new(&rules)) - return -1; - - if (smack_accesses_add(rules, subject, object, access_type)) { - smack_accesses_free(rules); - return -1; - } - - ret = smack_accesses_apply(rules); - smack_accesses_free(rules); - - return ret; -} - -void apply_app_process() { - set_appuser_groups(); - - if (setgid(SID_APP) != 0) { - //fprintf(stderr, "set group id failed errno: %d\n", errno); - exit(1); - } - - if (setuid(SID_APP) != 0) { - //fprintf(stderr, "set user id failed errno: %d\n", errno); - exit(1); - } -} - -void set_appuser_groups(void) { - - int fd = 0; - char buffer[5]; - gid_t t_gid = -1; - gid_t groups[APP_GROUPS_MAX]={0,}; - int cnt = 0; - - //groups[cnt++] = SID_DEVELOPER; - fd = sdb_open(APP_GROUP_LIST, O_RDONLY); - if (fd < 0) { - D("cannot get app's group lists from %s", APP_GROUP_LIST); - return; - } - for (;;) { - if (read_line(fd, buffer, sizeof buffer) < 0) { - break; - } - t_gid = strtoul(buffer, 0, 10); - errno = 0; - if(errno != 0) - { - D("cannot change string to integer: [%s]\n", buffer); - continue; - } - if (t_gid) { - if (cnt < APP_GROUPS_MAX) { - groups[cnt++] = t_gid; - } else { - D("cannot add groups more than %d", APP_GROUPS_MAX); - break; - } - } - } - if (cnt > 0) { - if (setgroups(sizeof(groups) / sizeof(groups[0]), groups) != 0) { - sdb_close(fd); - fprintf(stderr, "set groups failed errno: %d\n", errno); - exit(1); - } - } - sdb_close(fd); -} - int is_root_commands(const char *command) { int i = -1; for(i = 0; root_commands[i].path != NULL; i++) { diff --git a/src/sdktools.h b/src/sdktools.h index de805af..59d8d98 100644 --- a/src/sdktools.h +++ b/src/sdktools.h @@ -6,11 +6,12 @@ extern "C" { #endif #include +#define PERMITTED_ARGUMENT_SIZE 20 struct sudo_command { const char *command; const char *path; - //const char *arguments; + const char *arguments[PERMITTED_ARGUMENT_SIZE]; //const char *regx; //int permission; /* 0: root, 1: developer, 2: app*/ }; @@ -37,18 +38,11 @@ struct arg_permit_rule #define SDBD_LABEL_NAME "sdbd" #define SDK_HOME_LABEL_NAME "sdbd::home" -void init_sdk_arg_permit_rule_pattern(void); -int verify_commands(const char *arg1); int verify_root_commands(const char *arg1); int verify_app_path(const char* path); int regcmp(const char* pattern, const char* str); -int exec_app_standalone(const char* path); -char* clone_gdbserver_label_from_app(const char* app_path); -int set_smack_rules_for_gdbserver(const char* apppath, int mode); -void apply_app_process(); -void set_appuser_groups(void); int is_root_commands(const char *command); -int apply_sdb_rules(const char* subject, const char* object, const char* access_type); +int is_pkg_file_path(const char* path); #ifdef __cplusplus } diff --git a/src/services.c b/src/services.c index 2b2174e..e845e4f 100644 --- a/src/services.c +++ b/src/services.c @@ -42,8 +42,11 @@ #include #include -#define SYSTEM_INFO_KEY_MODEL "http://tizen.org/system/model_name" -#define SYSTEM_INFO_KEY_PLATFORM_NAME "http://tizen.org/system/platform.name" +#include +#include + +#include +#include typedef struct stinfo stinfo; @@ -84,6 +87,11 @@ static void dns_service(int fd, void *cookie) } #else +static int is_support_interactive_shell() +{ + return (!strncmp(g_capabilities.intershell_support, SDBD_CAP_RET_ENABLED, strlen(SDBD_CAP_RET_ENABLED))); +} + #if 0 extern int recovery_mode; @@ -164,23 +172,35 @@ void restart_tcp_service(int fd, void *cookie) sdb_close(fd); } +static int is_support_rootonoff() +{ + return (!strncmp(g_capabilities.rootonoff_support, SDBD_CAP_RET_ENABLED, strlen(SDBD_CAP_RET_ENABLED))); +} + void rootshell_service(int fd, void *cookie) { char buf[100]; char *mode = (char*) cookie; if (!strcmp(mode, "on")) { - if (rootshell_mode == 1) { - //snprintf(buf, sizeof(buf), "Already changed to developer mode\n"); - // do not show message - } else { - if (access("/bin/su", F_OK) == 0) { - rootshell_mode = 1; - //allows a permitted user to execute a command as the superuser - snprintf(buf, sizeof(buf), "Switched to 'root' account mode\n"); + if (getuid() == 0) { + if (rootshell_mode == 1) { + //snprintf(buf, sizeof(buf), "Already changed to developer mode\n"); + // do not show message } else { - snprintf(buf, sizeof(buf), "Permission denied\n"); + if (is_support_rootonoff()) { + rootshell_mode = 1; + //allows a permitted user to execute a command as the superuser + snprintf(buf, sizeof(buf), "Switched to 'root' account mode\n"); + } else { + snprintf(buf, sizeof(buf), "Permission denied\n"); + } + writex(fd, buf, strlen(buf)); } + } else { + D("need root permission for root shell: %d\n", getuid()); + rootshell_mode = 0; + snprintf(buf, sizeof(buf), "Permission denied\n"); writex(fd, buf, strlen(buf)); } } else if (!strcmp(mode, "off")) { @@ -190,10 +210,11 @@ void rootshell_service(int fd, void *cookie) writex(fd, buf, strlen(buf)); } } else { - snprintf(buf, sizeof(buf), "Unknown command option\n"); + snprintf(buf, sizeof(buf), "Unknown command option : %s\n", mode); writex(fd, buf, strlen(buf)); } D("set rootshell to %s\n", rootshell_mode == 1 ? "root" : "developer"); + free(mode); sdb_close(fd); } @@ -231,7 +252,7 @@ void reboot_service(int fd, void *arg) ret = android_reboot(ANDROID_RB_RESTART2, 0, (char *) arg); if (ret < 0) { - snprintf(buf, sizeof(buf), "reboot failed: %s\n", strerror(errno)); + snprintf(buf, sizeof(buf), "reboot failed: %s errno:%d\n", errno); writex(fd, buf, strlen(buf)); } free(arg); @@ -268,14 +289,14 @@ void inoti_service(int fd, void *arg) D( "inoti read failed\n"); goto done; } - - while ( i < length ) { - struct inotify_event *event = ( struct inotify_event * )&buffer[i]; + while (i >= 0 && i <= (length - EVENT_SIZE)) { + struct inotify_event *event = (struct inotify_event *) &buffer[i]; if (event->len) { - if ( event->mask & IN_CREATE) { + if (event->mask & IN_CREATE) { if (!(event->mask & IN_ISDIR)) { char *cspath = NULL; - int len = asprintf(&cspath, "%s/%s", CS_PATH, event->name); + int len = asprintf(&cspath, "%s/%s", CS_PATH, + event->name); D( "The file %s was created.\n", cspath); writex(fd, cspath, len); if (cspath != NULL) { @@ -284,6 +305,9 @@ void inoti_service(int fd, void *arg) } } } + if (i + EVENT_SIZE + event->len < event->len) { // in case of integer overflow + break; + } i += EVENT_SIZE + event->len; } } @@ -362,35 +386,41 @@ static int create_service_thread(void (*func)(int, void *), void *cookie) #if !SDB_HOST -static int create_subprocess(const char *cmd, const char *arg0, const char *arg1, pid_t *pid) +static void redirect_and_exec(int pts, const char *cmd, const char *argv[], const char *envp[]) { -#ifdef HAVE_WIN32_PROC - D("create_subprocess(cmd=%s, arg0=%s, arg1=%s)\n", cmd, arg0, arg1); - fprintf(stderr, "error: create_subprocess not implemented on Win32 (%s %s %s)\n", cmd, arg0, arg1); - return -1; -#else /* !HAVE_WIN32_PROC */ - char *devname; + dup2(pts, 0); + dup2(pts, 1); + dup2(pts, 2); + + sdb_close(pts); + + execve(cmd, argv, envp); +} + +static int create_subprocess(const char *cmd, pid_t *pid, const char *argv[], const char *envp[]) +{ + char devname[64]; int ptm; ptm = unix_open("/dev/ptmx", O_RDWR); // | O_NOCTTY); if(ptm < 0){ - D("[ cannot open /dev/ptmx - %s ]\n",strerror(errno)); + D("[ cannot open /dev/ptmx - errno:%d ]\n",errno); return -1; } if (fcntl(ptm, F_SETFD, FD_CLOEXEC) < 0) { - D("[ cannot set cloexec to /dev/ptmx - %s ]\n",strerror(errno)); + D("[ cannot set cloexec to /dev/ptmx - errno:%d ]\n",errno); } if(grantpt(ptm) || unlockpt(ptm) || - ((devname = (char*) ptsname(ptm)) == 0)){ - D("[ trouble with /dev/ptmx - %s ]\n", strerror(errno)); + ptsname_r(ptm, devname, sizeof(devname)) != 0 ){ + D("[ trouble with /dev/ptmx - errno:%d ]\n", errno); sdb_close(ptm); return -1; } *pid = fork(); if(*pid < 0) { - D("- fork failed: %s -\n", strerror(errno)); + D("- fork failed: errno:%d -\n", errno); sdb_close(ptm); return -1; } @@ -406,32 +436,34 @@ static int create_subprocess(const char *cmd, const char *arg0, const char *arg1 exit(-1); } - dup2(pts, 0); - dup2(pts, 1); - dup2(pts, 2); - - sdb_close(pts); sdb_close(ptm); // set OOM adjustment to zero { char text[64]; - snprintf(text, sizeof text, "/proc/%d/oom_score_adj", getpid()); + //snprintf(text, sizeof text, "/proc/%d/oom_score_adj", getpid()); + snprintf(text, sizeof text, "/proc/%d/oom_adj", getpid()); int fd = sdb_open(text, O_WRONLY); if (fd >= 0) { sdb_write(fd, "0", 1); sdb_close(fd); } else { // FIXME: not supposed to be here - D("sdb: unable to open %s due to %s\n", text, strerror(errno)); + D("sdb: unable to open %s due to errno:%d\n", text, errno); } } - verify_commands(arg1); - - execl(cmd, cmd, arg0, arg1, NULL); - fprintf(stderr, "- exec '%s' failed: %s (%d) -\n", - cmd, strerror(errno), errno); + if (should_drop_privileges()) { + if (argv[2] != NULL && getuid() == 0 && request_plugin_verification(SDBD_CMD_VERIFY_ROOTCMD, argv[2])) { + // do nothing + D("sdb: executes root commands!!:%s\n", argv[2]); + } else { + set_developer_privileges(); + } + } + redirect_and_exec(pts, cmd, argv, envp); + fprintf(stderr, "- exec '%s' failed: (errno:%d) -\n", + cmd, errno); exit(-1); } else { // Don't set child's OOM adjustment to zero. @@ -440,15 +472,14 @@ static int create_subprocess(const char *cmd, const char *arg0, const char *arg1 // """sdb: unable to open /proc/644/oom_adj""" seen in some logs. return ptm; } -#endif /* !HAVE_WIN32_PROC */ } #endif /* !SDB_HOST */ -#if SDB_HOST #define SHELL_COMMAND "/bin/sh" -#else -#define SHELL_COMMAND "/bin/sh" /* tizen specific */ -#endif +#define LOGIN_COMMAND "/bin/login" +#define SDK_USER "developer" +#define SUPER_USER "root" +#define LOGIN_CONFIG "/etc/login.defs" #if !SDB_HOST static void subproc_waiter_service(int fd, void *cookie) @@ -461,7 +492,6 @@ static void subproc_waiter_service(int fd, void *cookie) pid_t p = waitpid(pid, &status, 0); if (p == pid) { D("fd=%d, post waitpid(pid=%d) status=%04x\n", fd, p, status); - if (WIFEXITED(status)) { D("*** Exit code %d\n", WEXITSTATUS(status)); break; @@ -483,17 +513,160 @@ static void subproc_waiter_service(int fd, void *cookie) } } -static int create_subproc_thread(const char *name) +static void get_env(char *key, char **env) +{ + FILE *fp; + char buf[1024]; + int i; + char *s, *e, *value; + + fp = fopen (LOGIN_CONFIG, "r"); + if (NULL == fp) { + return; + } + + while (fgets(buf, (int) sizeof (buf), fp) != NULL) { + s = buf; + e = buf + (strlen(buf) - 1); + + while(*e == ' ' || *e == '\n' || *e == '\t') { + e--; + } + *(e+1) ='\0'; + + while(*s != '\0' && (*s == ' ' || *s == '\t' || *s == '\n')) { + s++; + } + + if (*s == '#' || *s == '\0') { + continue; + } + value = s + strcspn(s, " \t"); + *value++ = '\0'; + + if(!strcmp(buf, key)) { + *env = value; + break; + } + } + + fclose(fp); +} + +static int create_subproc_thread(const char *name, int lines, int columns) { stinfo *sti; sdb_thread_t t; int ret_fd; pid_t pid; + char *value = NULL; + char *trim_value = NULL; + char path[PATH_MAX]; + memset(path, 0, sizeof(path)); + + char *envp[] = { + "TERM=linux", /* without this, some programs based on screen can't work, e.g. top */ + "DISPLAY=:0", /* without this, some programs based on without launchpad can't work */ + NULL, + NULL, + NULL, + NULL, + NULL + }; - if(name) { - ret_fd = create_subprocess(SHELL_COMMAND, "-c", name, &pid); - } else { - ret_fd = create_subprocess(SHELL_COMMAND, "-", 0, &pid); + if (should_drop_privileges()) { + envp[2] = "HOME=/home/developer"; + get_env("ENV_PATH", &value); + } else { + get_env("ENV_SUPATH", &value); + if(value == NULL) { + get_env("ENV_ROOTPATH", &value); + } + envp[2] = "HOME=/root"; + } + if (value != NULL) { + trim_value = str_trim(value); + if (trim_value != NULL) { + // if string is not including 'PATH=', append it. + if (strncmp(trim_value, "PATH", 4)) { + snprintf(path, sizeof(path), "PATH=%s", trim_value); + } else { + snprintf(path, sizeof(path), "%s", trim_value); + } + envp[3] = path; + free(trim_value); + } else { + envp[3] = value; + } + } + + D("path env:%s,%s,%s,%s\n", envp[0], envp[1], envp[2], envp[3]); + + if(name) { // in case of shell execution directly + // Check the shell command validation. + if (!request_plugin_verification(SDBD_CMD_VERIFY_SHELLCMD, name)) { + D("This shell command is invalid. (%s)\n", name); + return -1; + } + + // Convert the shell command. + char *new_cmd = NULL; + new_cmd = malloc(SDBD_SHELL_CMD_MAX); + if(new_cmd == NULL) { + D("Cannot allocate the shell commnad buffer."); + return -1; + } + + memset(new_cmd, 0, SDBD_SHELL_CMD_MAX); + if(!request_plugin_cmd(SDBD_CMD_CONV_SHELLCMD, name, new_cmd, SDBD_SHELL_CMD_MAX)) { + D("Failed to convert the shell command. (%s)\n", name); + free(new_cmd); + return -1; + } + + D("converted cmd : %s\n", new_cmd); + + char *args[] = { + SHELL_COMMAND, + "-c", + NULL, + NULL, + }; + args[2] = new_cmd; + + ret_fd = create_subprocess(SHELL_COMMAND, &pid, args, envp); + free(new_cmd); + } else { // in case of shell interactively + // Check the capability for interactive shell support. + if (!is_support_interactive_shell()) { + D("This platform dose NOT support the interactive shell\n"); + return -1; + } + + char *args[] = { + SHELL_COMMAND, + "-", + NULL, + }; + ret_fd = create_subprocess(SHELL_COMMAND, &pid, args, envp); +#if 0 // FIXME: should call login command instead of /bin/sh + if (should_drop_privileges()) { + char *args[] = { + SHELL_COMMAND, + "-", + NULL, + }; + ret_fd = create_subprocess(SHELL_COMMAND, &pid, args, envp); + } else { + char *args[] = { + LOGIN_COMMAND, + "-f", + SUPER_USER, + NULL, + }; + ret_fd = create_subprocess(LOGIN_COMMAND, &pid, args, envp); + } +#endif } D("create_subprocess() ret_fd=%d pid=%d\n", ret_fd, pid); @@ -501,6 +674,18 @@ static int create_subproc_thread(const char *name) D("cannot create service thread\n"); return -1; } + + if (lines > 0 && columns > 0) { + D("shell size lines=%d, columns=%d\n", lines, columns); + struct winsize win_sz; + win_sz.ws_row = lines; + win_sz.ws_col = columns; + + if (ioctl(ret_fd, TIOCSWINSZ, &win_sz) < 0) { + D("failed to sync window size.\n"); + } + } + sti = malloc(sizeof(stinfo)); if(sti == 0) fatal("cannot allocate stinfo"); sti->func = subproc_waiter_service; @@ -540,7 +725,7 @@ static int create_sync_subprocess(void (*func)(int, void *), void* cookie) { //waitpid(pid, &ret, 0); } if (pid < 0) { - D("- fork failed: %s -\n", strerror(errno)); + D("- fork failed: errno:%d -\n", errno); sdb_close(s[0]); sdb_close(s[1]); D("cannot create sync service sub process\n"); @@ -584,25 +769,13 @@ static int create_syncproc_thread() #endif -#define UNKNOWN "unknown" -#define INFOBUF_MAXLEN 64 -#define INFO_VERSION "2.2.0" -typedef struct platform_info { - - char platform_info_version[INFOBUF_MAXLEN]; - char model_name[INFOBUF_MAXLEN]; // Emulator - char platform_name[INFOBUF_MAXLEN]; // Tizen - char platform_version[INFOBUF_MAXLEN]; // 2.2.1 - char profile_name[INFOBUF_MAXLEN]; // 2.2.1 -} pinfo; - static void get_platforminfo(int fd, void *cookie) { pinfo sysinfo; char *value = NULL; s_strncpy(sysinfo.platform_info_version, INFO_VERSION, strlen(INFO_VERSION)); - int r = system_info_get_platform_string(SYSTEM_INFO_KEY_MODEL, &value); + int r = system_info_get_platform_string("http://tizen.org/system/model_name", &value); if (r != SYSTEM_INFO_ERROR_NONE) { s_strncpy(sysinfo.model_name, UNKNOWN, strlen(UNKNOWN)); D("fail to get system model:%d\n", errno); @@ -614,7 +787,7 @@ static void get_platforminfo(int fd, void *cookie) { } } - r = system_info_get_platform_string(SYSTEM_INFO_KEY_PLATFORM_NAME, &value); + r = system_info_get_platform_string("http://tizen.org/system/platform.name", &value); if (r != SYSTEM_INFO_ERROR_NONE) { s_strncpy(sysinfo.platform_name, UNKNOWN, strlen(UNKNOWN)); D("fail to get platform name:%d\n", errno); @@ -657,6 +830,132 @@ static void get_platforminfo(int fd, void *cookie) { sdb_close(fd); } +static int put_key_value_string(char* buf, int offset, int buf_size, char* key, char* value) { + int len = 0; + if ((len = snprintf(buf+offset, buf_size-offset, "%s:%s\n", key, value)) > 0) { + return len; + } + return 0; +} + +static void get_capability(int fd, void *cookie) { + char cap_buffer[CAPBUF_SIZE] = {0,}; + uint16_t offset = 0; + + // Secure protocol support + offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, + "secure_protocol", g_capabilities.secure_protocol); + + // Interactive shell support + offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, + "intershell_support", g_capabilities.intershell_support); + + // File push/pull support + offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, + "filesync_support", g_capabilities.filesync_support); + + // USB protocol support + offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, + "usbproto_support", g_capabilities.usbproto_support); + + // Socket protocol support + offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, + "sockproto_support", g_capabilities.sockproto_support); + + // Root command support + offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, + "rootonoff_support", g_capabilities.rootonoff_support); + + // Zone support + offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, + "zone_support", g_capabilities.zone_support); + + // Multi-User support + offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, + "multiuser_support", g_capabilities.multiuser_support); + + // CPU Architecture of model + offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, + "cpu_arch", g_capabilities.cpu_arch); + + // Profile name + offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, + "profile_name", g_capabilities.profile_name); + + // Vendor name + offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, + "vendor_name", g_capabilities.vendor_name); + + // Platform version + offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, + "platform_version", g_capabilities.platform_version); + + // Product version + offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, + "product_version", g_capabilities.product_version); + + // Sdbd version + offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, + "sdbd_version", g_capabilities.sdbd_version); + + // Sdbd plugin version + offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, + "sdbd_plugin_version", g_capabilities.sdbd_plugin_version); + + // Window size synchronization support + offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, + "syncwinsz_support", g_capabilities.syncwinsz_support); + + + offset++; // for '\0' character + + writex(fd, &offset, sizeof(uint16_t)); + writex(fd, cap_buffer, offset); + + sdb_close(fd); +} + +static void sync_windowsize(int fd, void *cookie) { + int id, lines, columns; + char *size_info = cookie; + asocket *s = NULL; + + if (sscanf(size_info, "%d:%d:%d", &id, &lines, &columns) == 3) { + D("window size information: id=%d, lines=%d, columns=%d\n", id, lines, columns); + } + if((s = find_local_socket(id))) { + struct winsize win_sz; + win_sz.ws_row = lines; + win_sz.ws_col = columns; + + if (ioctl(s->fd, TIOCSWINSZ, &win_sz) < 0) { + D("failed to sync window size.\n"); + return; + } + D("success to sync window size.\n"); + } +} + +const unsigned COMMAND_TIMEOUT = 10000; +void get_boot(int fd, void *cookie) { + char buf[2] = { 0, }; + char *mode = (char*) cookie; + int time = 0; + int interval = 1000; + while (time < COMMAND_TIMEOUT) { + if (booting_done == 1) { + D("get_boot:platform booting is done\n"); + snprintf(buf, sizeof(buf), "%s", "1"); + break; + } + D("get_boot:platform booting is in progress\n"); + sdb_sleep_ms(interval); + time += interval; + } + writex(fd, buf, strlen(buf)); + sdb_close(fd); +} + int service_to_fd(const char *name) { int ret = -1; @@ -665,9 +964,22 @@ int service_to_fd(const char *name) int port = atoi(name + 4); name = strchr(name + 4, ':'); if(name == 0) { - ret = socket_loopback_client(port, SOCK_STREAM); - if (ret >= 0) + if (is_emulator()){ + ret = socket_ifr_client(port , SOCK_STREAM, "eth0"); + } else { + ret = socket_ifr_client(port , SOCK_STREAM, "usb0"); + if (ret < 0) { + if (ifconfig(SDB_FORWARD_IFNAME, SDB_FORWARD_INTERNAL_IP, SDB_FORWARD_INTERNAL_MASK, 1) == 0) { + ret = socket_ifr_client(port , SOCK_STREAM, SDB_FORWARD_IFNAME); + } + } + } + if (ret < 0) { + ret = socket_loopback_client(port, SOCK_STREAM); + } + if (ret >= 0) { disable_tcp_nagle(ret); + } } else { #if SDB_HOST sdb_mutex_lock(&dns_lock); @@ -709,9 +1021,14 @@ int service_to_fd(const char *name) ret = create_service_thread(log_service, get_log_file_path(name + 4)); }*/ else if(!HOST && !strncmp(name, "shell:", 6)) { if(name[6]) { - ret = create_subproc_thread(name + 6); + ret = create_subproc_thread(name + 6, 0, 0); } else { - ret = create_subproc_thread(0); + ret = create_subproc_thread(NULL, 0, 0); + } + } else if(!strncmp(name, "eshell:", 7)) { + int lines, columns; + if (sscanf(name+7, "%d:%d", &lines, &columns) == 2) { + ret = create_subproc_thread(NULL, lines, columns); } } else if(!strncmp(name, "sync:", 5)) { //ret = create_service_thread(file_sync_service, NULL); @@ -731,22 +1048,27 @@ int service_to_fd(const char *name) } else if(!strncmp(name, "restore:", 8)) { ret = backup_service(RESTORE, NULL); }*/ else if(!strncmp(name, "root:", 5)) { - ret = create_service_thread(rootshell_service, (void *)(name+5)); - } else if(!strncmp(name, "tcpip:", 6)) { - int port; - /*if (sscanf(name + 6, "%d", &port) == 0) { - port = 0; - }*/ - port = DEFAULT_SDB_LOCAL_TRANSPORT_PORT; - ret = create_service_thread(restart_tcp_service, (void *)port); - } else if(!strncmp(name, "usb:", 4)) { - ret = create_service_thread(restart_usb_service, NULL); + char* service_name = NULL; + + service_name = strdup(name+5); + ret = create_service_thread(rootshell_service, (void *)(service_name)); } else if(!strncmp(name, "cs:", 5)) { ret = create_service_thread(inoti_service, NULL); #endif } else if(!strncmp(name, "sysinfo:", 8)){ ret = create_service_thread(get_platforminfo, 0); + } else if(!strncmp(name, "capability:", 11)){ + ret = create_service_thread(get_capability, 0); + } else if(!strncmp(name, "boot:", 5)){ + if (is_emulator()) { + ret = create_service_thread(get_boot, 0); + } + } else if(!strncmp(name, "shellconf:", 10)){ + if(!strncmp(name+10, "syncwinsz:", 10)){ + ret = create_service_thread(sync_windowsize, name+20); + } } + if (ret >= 0) { if (close_on_exec(ret) < 0) { D("failed to close fd exec\n"); diff --git a/src/socket_local_client.c b/src/socket_local_client.c index 63d17ef..586a71a 100644 --- a/src/socket_local_client.c +++ b/src/socket_local_client.c @@ -38,11 +38,11 @@ int socket_local_client(const char *name, int namespaceId, int type) #include #include "socket_local.h" - +#include "strutils.h" #define LISTEN_BACKLOG 4 /* Documented in header file. */ -int socket_make_sockaddr_un(const char *name, int namespaceId, +int socket_make_sockaddr_un(const char *name, int namespaceId, struct sockaddr_un *p_addr, socklen_t *alen) { memset (p_addr, 0, sizeof (*p_addr)); @@ -62,7 +62,7 @@ int socket_make_sockaddr_un(const char *name, int namespaceId, * Note: The path in this case is *not* supposed to be * '\0'-terminated. ("man 7 unix" for the gory details.) */ - + p_addr->sun_path[0] = 0; memcpy(p_addr->sun_path + 1, name, namelen); #else /*HAVE_LINUX_LOCAL_SOCKET_NAMESPACE*/ @@ -70,37 +70,37 @@ int socket_make_sockaddr_un(const char *name, int namespaceId, namelen = strlen(name) + strlen(FILESYSTEM_SOCKET_PREFIX); /* unix_path_max appears to be missing on linux */ - if (namelen > sizeof(*p_addr) + if (namelen > sizeof(*p_addr) - offsetof(struct sockaddr_un, sun_path) - 1) { goto error; } - strcpy(p_addr->sun_path, FILESYSTEM_SOCKET_PREFIX); - strcat(p_addr->sun_path, name); + s_strncpy(p_addr->sun_path, FILESYSTEM_SOCKET_PREFIX, strlen(FILESYSTEM_SOCKET_PREFIX)); + strncat(p_addr->sun_path, name, strlen(name)); #endif /*HAVE_LINUX_LOCAL_SOCKET_NAMESPACE*/ break; case ANDROID_SOCKET_NAMESPACE_RESERVED: namelen = strlen(name) + strlen(ANDROID_RESERVED_SOCKET_PREFIX); /* unix_path_max appears to be missing on linux */ - if (namelen > sizeof(*p_addr) + if (namelen > sizeof(*p_addr) - offsetof(struct sockaddr_un, sun_path) - 1) { goto error; } - strcpy(p_addr->sun_path, ANDROID_RESERVED_SOCKET_PREFIX); - strcat(p_addr->sun_path, name); + s_strncpy(p_addr->sun_path, ANDROID_RESERVED_SOCKET_PREFIX, strlen(ANDROID_RESERVED_SOCKET_PREFIX)); + strncat(p_addr->sun_path, name, strlen(name)); break; case ANDROID_SOCKET_NAMESPACE_FILESYSTEM: namelen = strlen(name); /* unix_path_max appears to be missing on linux */ - if (namelen > sizeof(*p_addr) + if (namelen > sizeof(*p_addr) - offsetof(struct sockaddr_un, sun_path) - 1) { goto error; } - strcpy(p_addr->sun_path, name); + s_strncpy(p_addr->sun_path, name, strlen(name)); break; default: // invalid namespace id @@ -118,10 +118,10 @@ error: * connect to peer named "name" on fd * returns same fd or -1 on error. * fd is not closed on error. that's your job. - * + * * Used by AndroidSocketImpl */ -int socket_local_client_connect(int fd, const char *name, int namespaceId, +int socket_local_client_connect(int fd, const char *name, int namespaceId, int type) { struct sockaddr_un addr; @@ -144,7 +144,7 @@ error: return -1; } -/** +/** * connect to peer named "name" * returns fd or -1 on error */ diff --git a/src/socket_loopback_client.c b/src/socket_loopback_client.c index 69fd87f..de229c1 100644 --- a/src/socket_loopback_client.c +++ b/src/socket_loopback_client.c @@ -16,7 +16,7 @@ // libs/cutils/socket_loopback_client.c #include "sockets.h" - +#include #include #include #include @@ -28,10 +28,14 @@ #include #include #include +#include +#include +#include #endif +#include "strutils.h" /* Connect to port on the loopback IP interface. type is - * SOCK_STREAM or SOCK_DGRAM. + * SOCK_STREAM or SOCK_DGRAM. * return is a file descriptor or -1 on error */ int socket_loopback_client(int port, int type) @@ -53,6 +57,94 @@ int socket_loopback_client(int port, int type) } return s; +} + +int socket_ifr_client(int port, int type, char *ifr_dev) +{ + int s; + struct ifreq ifr; + struct sockaddr_in addr; + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + + s = socket(AF_INET, SOCK_DGRAM, 0); + if(s < 0) { + return -1; + } + ifr.ifr_addr.sa_family = AF_INET; + s_strncpy(ifr.ifr_name, ifr_dev, IFNAMSIZ-1); + + if (ioctl(s, SIOCGIFADDR, &ifr) < 0 ) { + close(s); + return -1; + } + + char buf[1025] = {0, }; + inet_ntop(AF_INET, &((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr, buf, sizeof(buf)); + addr.sin_addr.s_addr = inet_addr(buf); + close(s); + + s = socket(AF_INET, type, 0); + if(s < 0) { + return -1; + } + + if(connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + close(s); + return -1; + } + + return s; } +/* Simple implementation of ifconfig. + * activate: '0' causes the ifname driver to be shut down. + */ +int ifconfig(char *ifname, char *address, char *netmask, int activated) { + struct ifreq ifr; + struct sockaddr_in *sin; + int sockfd; + + if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + fprintf(stderr, "cannot open socket\n"); + return -1; + } + + memset(&ifr, 0, sizeof(struct ifreq)); + s_strncpy(ifr.ifr_name, ifname, IFNAMSIZ-1); + + sin = (struct sockaddr_in *) &ifr.ifr_addr; + sin->sin_family = AF_INET; + sin->sin_port = 0; + sin->sin_addr.s_addr = inet_addr(address); + + if (ioctl(sockfd, SIOCSIFADDR, &ifr) < 0) { + fprintf(stderr,"cannot set SIOCSIFADDR flags: %s(errno:%d)\n", address, errno); + close(sockfd); + return -1; + } + + sin->sin_addr.s_addr = inet_addr(netmask); + if (ioctl(sockfd, SIOCSIFNETMASK, &ifr) < 0) { + fprintf(stderr,"cannot set SIOCSIFNETMASK flags: %s(errno:%d)\n", netmask, errno); + close(sockfd); + return -1; + } + + if (activated) { + ifr.ifr_flags |= IFF_UP | IFF_RUNNING; + } else { + ifr.ifr_flags |= ~IFF_UP; + } + if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) { + fprintf(stderr,"cannot set SIOCGIFFLAGS flags: errno:%d\n", errno); + close(sockfd); + return -1; + } + + close(sockfd); + return 0; +} diff --git a/src/socket_network_client.c b/src/socket_network_client.c index d2b436a..326040b 100644 --- a/src/socket_network_client.c +++ b/src/socket_network_client.c @@ -33,31 +33,61 @@ /* Connect to port on the IP interface. type is - * SOCK_STREAM or SOCK_DGRAM. + * SOCK_STREAM or SOCK_DGRAM. * return is a file descriptor or -1 on error */ int socket_network_client(const char *host, int port, int type) { - struct hostent *hp; + struct hostent hostbuf, *hp; struct sockaddr_in addr; int s; + size_t hstbuflen = 1024; + int res, herr; + char *tmphstbuf; - hp = gethostbyname(host); - if(hp == 0) return -1; - + tmphstbuf = malloc(hstbuflen); + if (tmphstbuf == NULL) { + return -1; + } + + while ((res = gethostbyname_r(host, &hostbuf, tmphstbuf, hstbuflen, &hp, &herr)) == ERANGE) { + // enlarge the buffer + hstbuflen *= 2; + tmphstbuf = realloc(tmphstbuf, hstbuflen); + if (tmphstbuf == NULL) { + return -1; + } + } + if (res || hp == NULL) { + if (tmphstbuf != NULL) { + free(tmphstbuf); + } + return -1; + } memset(&addr, 0, sizeof(addr)); addr.sin_family = hp->h_addrtype; addr.sin_port = htons(port); memcpy(&addr.sin_addr, hp->h_addr, hp->h_length); s = socket(hp->h_addrtype, type, 0); - if(s < 0) return -1; + if(s < 0) { + if (tmphstbuf != NULL) { + free(tmphstbuf); + } + return -1; + } if(connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { close(s); + + if (tmphstbuf != NULL) { + free(tmphstbuf); + } return -1; } - + if (tmphstbuf != NULL) { + free(tmphstbuf); + } return s; } diff --git a/src/sockets.c b/src/sockets.c index c621f47..16e746e 100644 --- a/src/sockets.c +++ b/src/sockets.c @@ -25,6 +25,7 @@ #define TRACE_TAG TRACE_SOCKETS #include "sdb.h" +#include "strutils.h" SDB_MUTEX_DEFINE( socket_list_lock ); @@ -152,7 +153,7 @@ static int local_socket_enqueue(asocket *s, apacket *p) continue; } if((r == 0) || (errno != EAGAIN)) { - D( "LS(%d): not ready, errno=%d: %s\n", s->id, errno, strerror(errno) ); + D( "LS(%d): not ready, errno=%d\n", s->id, errno); s->close(s); return 1; /* not ready (error) */ } else { @@ -199,7 +200,6 @@ static void local_socket_close(asocket *s) static void local_socket_destroy(asocket *s) { apacket *p, *n; - int exit_on_close = s->exit_on_close; D("LS(%d): destroying fde.fd=%d\n", s->id, s->fde.fd); @@ -216,11 +216,6 @@ static void local_socket_destroy(asocket *s) } remove_socket(s); free(s); - - if (exit_on_close) { - D("local_socket_destroy: exiting\n"); - exit(1); - } } @@ -428,15 +423,6 @@ asocket *create_local_service_socket(const char *name) s = create_local_socket(fd); D("LS(%d): bound to '%s' via %d\n", s->id, name, fd); -#if !SDB_HOST - if ((!strncmp(name, "root:", 5) && getuid() != 0) - || !strncmp(name, "usb:", 4) - || !strncmp(name, "tcpip:", 6)) { - D("LS(%d): enabling exit_on_close\n", s->id); - s->exit_on_close = 1; - } -#endif - return s; } @@ -554,7 +540,7 @@ void connect_to_remote(asocket *s, const char *destination) p->msg.command = A_OPEN; p->msg.arg0 = s->id; p->msg.data_length = len; - strcpy((char*) p->data, destination); + s_strncpy((char*) p->data, destination, len); send_packet(p, s->transport); } diff --git a/src/sockets.h b/src/sockets.h index 8e8196a..de2269f 100644 --- a/src/sockets.h +++ b/src/sockets.h @@ -83,18 +83,24 @@ static inline int android_get_control_socket(const char *name) // Normal filesystem namespace #define ANDROID_SOCKET_NAMESPACE_FILESYSTEM 2 +#define SDB_FORWARD_IFNAME "lo:sdb" +#define SDB_FORWARD_INTERNAL_IP "192.168.129.3" +#define SDB_FORWARD_INTERNAL_MASK "255.255.255.0" + extern int socket_loopback_client(int port, int type); extern int socket_network_client(const char *host, int port, int type); extern int socket_loopback_server(int port, int type); extern int socket_local_server(const char *name, int namespaceId, int type); extern int socket_local_server_bind(int s, const char *name, int namespaceId); -extern int socket_local_client_connect(int fd, +extern int socket_local_client_connect(int fd, const char *name, int namespaceId, int type); extern int socket_local_client(const char *name, int namespaceId, int type); extern int socket_inaddr_any_server(int port, int type); - + +int socket_ifr_client(int port, int type, char *ifr_dev); +int ifconfig(char *ifname, char *address, char *netmask, int activated); #ifdef __cplusplus } #endif -#endif /* __CUTILS_SOCKETS_H */ +#endif /* __CUTILS_SOCKETS_H */ diff --git a/src/strutils.c b/src/strutils.c index 934cbdb..910e3be 100644 --- a/src/strutils.c +++ b/src/strutils.c @@ -12,10 +12,13 @@ size_t tokenize(const char *str, const char *delim, char *tokens[], size_t max_tokens ) { int cnt = 0; - char tmp[PATH_MAX]; + char tmp[PATH_MAX+1]; + char *ptr; strncpy(tmp, str, PATH_MAX); - char *p = strtok(tmp, delim); + tmp[PATH_MAX] = '\0'; + + char *p = strtok_r(tmp, delim, &ptr); if (max_tokens < 1 || max_tokens > MAX_TOKENS) { max_tokens = 1; } @@ -23,7 +26,7 @@ size_t tokenize(const char *str, const char *delim, char *tokens[], size_t max_t if (p != NULL) { tokens[cnt++] = strdup(p); while(cnt < max_tokens && p != NULL) { - p = strtok(NULL, delim); + p = strtok_r(NULL, delim, &ptr); if (p != NULL) { tokens[cnt++] = strdup(p); } @@ -69,12 +72,15 @@ int read_line(const int fd, char* ptr, const unsigned int maxlen) * strncpy(ntbs, source, sizeof(ntbs)-1); * ntbs[sizeof(ntbs)-1] = '\0' */ + char *s_strncpy(char *dest, const char *source, size_t n) { + char *start = dest; - while (n && (*dest++ = *source++)) { + while(n && (*dest++ = *source++)) { n--; } + if (n) { while (--n) { *dest++ = '\0'; @@ -82,4 +88,3 @@ char *s_strncpy(char *dest, const char *source, size_t n) { } return start; } - diff --git a/src/sysdeps.h b/src/sysdeps.h index 0b70222..d99a2d4 100644 --- a/src/sysdeps.h +++ b/src/sysdeps.h @@ -293,6 +293,7 @@ static __inline__ int sdb_is_absolute_host_path( const char* path ) #include #include #include +#include #define OS_PATH_SEPARATOR '/' #define OS_PATH_SEPARATOR_STR "/" @@ -498,7 +499,10 @@ static __inline__ int sdb_socketpair( int sv[2] ) static __inline__ void sdb_sleep_ms( int mseconds ) { - usleep( mseconds*1000 ); + struct timespec ts; + ts.tv_sec = mseconds / 1000; + ts.tv_nsec = (mseconds % 1000) * 1000000; + nanosleep(&ts, NULL); } static __inline__ int sdb_mkdir(const char* path, int mode) @@ -527,6 +531,8 @@ static __inline__ int sdb_is_absolute_host_path( const char* path ) return path[0] == '/'; } +#include "strutils.h" + static __inline__ char* ansi_to_utf8(const char *str) { // Not implement! @@ -536,7 +542,7 @@ static __inline__ char* ansi_to_utf8(const char *str) len = strlen(str); utf8 = (char *)calloc(len+1, sizeof(char)); - strcpy(utf8, str); + s_strncpy(utf8, str, strlen(str)); return utf8; } diff --git a/src/transport.c b/src/transport.c index 1d91b80..e63e5d6 100644 --- a/src/transport.c +++ b/src/transport.c @@ -45,11 +45,13 @@ static void dump_hex( const unsigned char* ptr, size_t len ) if (len2 > MAX_DUMP_HEX_LEN) len2 = MAX_DUMP_HEX_LEN; + int pbSize = sizeof(buffer); for (nn = 0; nn < len2; nn++) { - sprintf(pb, "%02x", ptr[nn]); + snprintf(pb, pbSize, "%02x", ptr[nn]); pb += 2; + pbSize -= 2; } - sprintf(pb++, " "); + *pb++ = ' '; for (nn = 0; nn < len2; nn++) { int c = ptr[nn]; @@ -150,7 +152,7 @@ read_packet(int fd, const char* name, apacket** ppacket) len -= r; p += r; } else { - D("%s: read_packet (fd=%d), error ret=%d errno=%d: %s\n", name, fd, r, errno, strerror(errno)); + D("%s: read_packet (fd=%d), error ret=%d errno=%d\n", name, fd, r, errno); if((r < 0) && (errno == EINTR)) continue; return -1; } @@ -187,7 +189,7 @@ write_packet(int fd, const char* name, apacket** ppacket) len -= r; p += r; } else { - D("%s: write_packet (fd=%d) error ret=%d errno=%d: %s\n", name, fd, r, errno, strerror(errno)); + D("%s: write_packet (fd=%d) error ret=%d errno=%d\n", name, fd, r, errno); if((r < 0) && (errno == EINTR)) continue; return -1; } @@ -533,8 +535,8 @@ transport_read_action(int fd, struct tmsg* m) p += r; } else { if((r < 0) && (errno == EINTR)) continue; - D("transport_read_action: on fd %d, error %d: %s\n", - fd, errno, strerror(errno)); + D("transport_read_action: on fd %d, error %d\n", + fd, errno); return -1; } } @@ -555,8 +557,8 @@ transport_write_action(int fd, struct tmsg* m) p += r; } else { if((r < 0) && (errno == EINTR)) continue; - D("transport_write_action: on fd %d, error %d: %s\n", - fd, errno, strerror(errno)); + D("transport_write_action: on fd %d, error %d\n", + fd, errno); return -1; } } @@ -886,6 +888,10 @@ void close_usb_devices() void register_socket_transport(int s, const char *serial, int port, int local, const char *device_name) { atransport *t = calloc(1, sizeof(atransport)); + if (t == NULL) { + D("failed to allocate memory of transport struct\n"); + return; + } char buff[32]; if (!serial) { @@ -977,24 +983,49 @@ void unregister_all_tcp_transports() #endif -int get_connected_device_count(transport_type type) /* tizen specific */ +int get_connected_count(transport_type type) /* tizen specific */ { int cnt = 0; atransport *t; sdb_mutex_lock(&transport_lock); for(t = transport_list.next; t != &transport_list; t = t->next) { - if (type == kTransportUsb && t->type == kTransportUsb) + if (type == kTransportAny || type == t->type) cnt++; } sdb_mutex_unlock(&transport_lock); - D("connected device count:%d\n",cnt); + if (type == kTransportUsb) { + D("connected device count:%d\n",cnt); + } return cnt; } +void broadcast_transport(apacket *p) +{ + atransport *t; + sdb_mutex_lock(&transport_lock); + for(t = transport_list.next; t != &transport_list; t = t->next) { + D("broadcast device transport:%d\n", t->connection_state); + apacket* ap = get_apacket(); + copy_packet(ap, p); + + send_packet(ap, t); + if (is_pwlocked()) { + t->connection_state = CS_PWLOCK; + } else { + t->connection_state = CS_DEVICE; + } + } + sdb_mutex_unlock(&transport_lock); +} + void register_usb_transport(usb_handle *usb, const char *serial, unsigned writeable) { - atransport *t = calloc(1, sizeof(atransport)); char device_name[256]; + atransport *t = calloc(1, sizeof(atransport)); + if (t == NULL) { + D("failed to allocate memory of transport struct\n"); + return; + } D("transport: %p init'ing for usb_handle %p (sn='%s')\n", t, usb, serial ? serial : ""); @@ -1004,7 +1035,7 @@ void register_usb_transport(usb_handle *usb, const char *serial, unsigned writea } /* tizen specific */ - sprintf(device_name, "device-%d",get_connected_device_count(kTransportUsb)+1); + snprintf(device_name, sizeof(device_name), "device-%d",get_connected_count(kTransportUsb)+1); t->device_name = strdup(device_name); register_transport(t); } @@ -1042,7 +1073,7 @@ int readx(int fd, void *ptr, size_t len) p += r; } else { if (r < 0) { - D("readx: fd=%d error %d: %s\n", fd, errno, strerror(errno)); + D("readx: fd=%d error %d\n", fd, errno); if (errno == EINTR) continue; } else { @@ -1075,7 +1106,7 @@ int writex(int fd, const void *ptr, size_t len) p += r; } else { if (r < 0) { - D("writex: fd=%d error %d: %s\n", fd, errno, strerror(errno)); + D("writex: fd=%d error %d\n", fd, errno); if (errno == EINTR) continue; } else { diff --git a/src/transport_local.c b/src/transport_local.c index 743ef2d..8e8029b 100644 --- a/src/transport_local.c +++ b/src/transport_local.c @@ -173,9 +173,9 @@ int get_devicename_from_shdmem(int port, char *device_name) vms = strstr((char*)shared_memory, VMS_PATH); if (vms != NULL) - strncpy(device_name, vms+strlen(VMS_PATH), DEVICENAME_MAX); + s_strncpy(device_name, vms+strlen(VMS_PATH), DEVICENAME_MAX); else - strncpy(device_name, DEFAULT_DEVICENAME, DEVICENAME_MAX); + s_strncpy(device_name, DEFAULT_DEVICENAME, DEVICENAME_MAX); #else /* _WIN32*/ HANDLE hMapFile; @@ -202,9 +202,9 @@ int get_devicename_from_shdmem(int port, char *device_name) vms = strstr((char*)pBuf, VMS_PATH); if (vms != NULL) - strncpy(device_name, vms+strlen(VMS_PATH), DEVICENAME_MAX); + s_strncpy(device_name, vms+strlen(VMS_PATH), DEVICENAME_MAX); else - strncpy(device_name, DEFAULT_DEVICENAME, DEVICENAME_MAX); + s_strncpy(device_name, DEFAULT_DEVICENAME, DEVICENAME_MAX); CloseHandle(hMapFile); #endif D("init device name %s on port %d\n", device_name, port); @@ -253,7 +253,7 @@ static void *client_socket_thread(void *x) static void *server_socket_thread(void * arg) { int serverfd, fd; - struct sockaddr addr; + struct sockaddr_in addr; socklen_t alen; int port = (int)arg; @@ -261,6 +261,7 @@ static void *server_socket_thread(void * arg) serverfd = -1; for(;;) { if(serverfd == -1) { + // socket_inaddr_any_server returns -1 if there is any error serverfd = socket_inaddr_any_server(port, SOCK_STREAM); if(serverfd < 0) { D("server: cannot bind socket yet\n"); @@ -280,14 +281,21 @@ static void *server_socket_thread(void * arg) pthread_cond_broadcast(¬i_cond); } - fd = sdb_socket_accept(serverfd, &addr, &alen); + fd = sdb_socket_accept(serverfd, (struct sockaddr *)&addr, &alen); if(fd >= 0) { D("server: new connection on fd %d\n", fd); if (close_on_exec(fd) < 0) { D("failed to close fd exec\n"); } disable_tcp_nagle(fd); - register_socket_transport(fd, "host", port, 1, NULL); + + // Check the peer ip validation. + if (!is_emulator() + && !request_plugin_verification(SDBD_CMD_VERIFY_PEERIP, inet_ntoa(addr.sin_addr))) { + sdb_close(fd); + } else { + register_socket_transport(fd, "host", port, 1, NULL); + } } } D("transport: server_socket_thread() exiting\n"); @@ -485,35 +493,170 @@ static int send_msg_to_host_from_guest(const char *hostname, int host_port, char return 0; } -static void notify_sdbd_startup() { +int connect_nonb(int sockfd, const struct sockaddr *saptr, socklen_t salen, + int nsec) { + int flags, n, error; + socklen_t len; + fd_set rset, wset; + struct timeval tval; + + flags = fcntl(sockfd, F_GETFL, 0); + if(fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) == -1) { + D("failed to set file O_NONBLOCK status flag for socket %d: errno:%d\n", + sockfd, errno); + } + + error = 0; + if ((n = connect(sockfd, (struct sockaddr *) saptr, salen)) < 0) + if (errno != EINPROGRESS) + return (-1); + + /* Do whatever we want while the connect is taking place. */ + + if (n == 0) + goto done; + /* connect completed immediately */ + + FD_ZERO(&rset); + FD_SET(sockfd, &rset); + wset = rset; + tval.tv_sec = nsec; + tval.tv_usec = 0; + if ((n = select(sockfd + 1, &rset, &wset, NULL, nsec ? &tval : NULL)) + == 0) { + sdb_close(sockfd); /* timeout */ + errno = ETIMEDOUT; + return (-1); + } + if (FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset)) { + len = sizeof(error); + if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) + return (-1); /* Solaris pending error */ + } else + D("select error: sockfd not set\n"); + + done: + if(fcntl(sockfd, F_SETFL, flags) == -1) { /* restore file status flags */ + D("failed to restore file status flag for socket %d\n", + sockfd); + } + + if (error) { + sdb_close(sockfd); /* just in case */ + errno = error; + return (-1); + } + return (0); +} + +static int send_msg_to_localhost_from_guest(const char *host_ip, int local_port, char *request, int sock_type) { + int ret, s; + struct sockaddr_in server; + int connect_timeout = 1; + memset( &server, 0, sizeof(server) ); + server.sin_family = AF_INET; + server.sin_port = htons(local_port); + server.sin_addr.s_addr = inet_addr(host_ip); + + D("try to send notification to host(%s:%d) using %s:[%s]\n", host_ip, local_port, (sock_type == 0) ? "tcp" : "udp", request); + + if (sock_type == 0) { + s = socket(AF_INET, SOCK_STREAM, 0); + } else { + s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + } + if (s < 0) { + D("could not create socket\n"); + return -1; + } + ret = connect_nonb(s, (struct sockaddr*) &server, sizeof(server), connect_timeout); + if (ret < 0) { + D("could not connect to server\n"); + sdb_close(s); + return -1; + } + if (writex(s, request, strlen(request)) != 0) { + D("could not send notification request to host\n"); + sdb_close(s); + return -1; + } + sdb_close(s); + D("sent notification request to host\n"); + + return 0; +} + +// send the "emulator" request to sdbserver +static void notify_sdbd_startup_thread() { char buffer[512]; char request[512]; - SdbdCommandlineArgs *sdbd_args = &sdbd_commandline_args; /* alias */ + SdbdCommandlineArgs *sdbd_args = &sdbd_commandline_args; // alias // send the request to sdbserver - const char *vm_name = sdbd_args->emulator.host; - int sdbd_port = sdbd_args->sdbd_port; + char vm_name[256]={0,}; + char host_ip[256] = {0,}; + char guest_ip[256] = {0,}; int sensors_port = sdbd_args->sensors.port; + int emulator_port = sdbd_args->emulator.port; - - if (sdbd_port <= 0 || vm_name == NULL) { + int r = get_emulator_name(vm_name, sizeof vm_name); + int time = 0; + //int try_limit_time = -1; // try_limit_time < 0 if unlimited + if (sensors_port < 0 || emulator_port < 0 || r < 0) { return; } - - // tell qemu sdbd is just started with udp - char sensord_buf[16]; - snprintf(sensord_buf, sizeof sensord_buf, "2\n"); - if (send_msg_to_host_from_guest(sdbd_args->sensors.host, sensors_port, sensord_buf, IPPROTO_UDP) < 0) { - D("could not send sensord noti request\n"); + if (get_emulator_hostip(host_ip, sizeof host_ip) == -1) { + D("failed to get emulator host ip\n"); + return; } + // XXX: Known issue - log collision + while (1) { + // Trial limitation reached. terminate notify thread. + /*if (0 <= try_limit_time && try_limit_time <= time) { + break; + }*/ + // If there is any connected (via TCP/IP) SDB server, sleep 10 secs + if (get_connected_count(kTransportLocal) > 0) { + if (time >= 0) { + time = 0; + D("notify_sdbd_startup() success after %d trial(s)\n", time); + } + sleep(10); + continue; + } + + if (get_emulator_guestip(guest_ip, sizeof guest_ip) == -1) { + D("failed to get emulator guest ip\n"); + goto sleep_and_continue; + } - // tell sdb server emulator's vms name and forward port - snprintf(request, sizeof request, "host:emulator:%d:%s", sdbd_port, vm_name); - snprintf(buffer, sizeof buffer, "%04x%s", strlen(request), request); + // tell qemu sdbd is just started with udp + if (send_msg_to_localhost_from_guest(host_ip, sensors_port, "2\n", 1) < 0) { + D("could not send sensord noti request, try again %dth\n", time+1); + goto sleep_and_continue; + } + + // tell sdb server emulator's vms name + // TODO: should we use host:emulator request? let's talk about this! - if (send_msg_to_host_from_guest(sdbd_args->sdb.host, sdbd_args->sdb.port, buffer, IPPROTO_TCP) < 0) { - D("could not send sdbd noti request. it might sdb server has not been started yet.\n"); + if (!strncmp(host_ip, QEMU_FORWARD_IP, sizeof host_ip)) { + snprintf(request, sizeof request, "host:emulator:%d:%s", (emulator_port + 1), vm_name); + } else { + snprintf(request, sizeof request, "host:connect:%s:%d", guest_ip, DEFAULT_SDB_LOCAL_TRANSPORT_PORT); + } + D("[%s:%d] request:%s \n", __FUNCTION__, __LINE__, request); + snprintf(buffer, sizeof buffer, "%04x%s", strlen(request), request ); + + if (send_msg_to_localhost_from_guest(host_ip, DEFAULT_SDB_PORT, buffer, 0) <0) { + D("could not send sdbd noti request. it might sdb server has not been started yet.\n"); + goto sleep_and_continue; + } + //LOGI("sdbd noti request sent.\n"); + +sleep_and_continue: + time++; + sleep(1); } } @@ -560,7 +703,11 @@ void local_init(int port) sdb_mutex_lock(®ister_noti_lock); pthread_cond_wait(¬i_cond, ®ister_noti_lock); - notify_sdbd_startup(); + // thread start + if(sdb_thread_create(&thr, notify_sdbd_startup_thread, NULL)) { + fatal("cannot create notify_sdbd_startup_thread"); + //notify_sdbd_startup(); // defensive code + } sdb_mutex_unlock(®ister_noti_lock); } } diff --git a/src/usb_linux.c b/src/usb_linux.c index cd72c07..d7e8399 100644 --- a/src/usb_linux.c +++ b/src/usb_linux.c @@ -437,8 +437,8 @@ int usb_write(usb_handle *h, const void *_data, int len) n = usb_bulk_write(h, data, xfer); if(n != xfer) { - D("ERROR: n = %d, errno = %d (%s)\n", - n, errno, strerror(errno)); + D("ERROR: n = %d, errno = %d\n", + n, errno); return -1; } @@ -475,8 +475,8 @@ int usb_read(usb_handle *h, void *_data, int len) } continue; } - D("ERROR: n = %d, errno = %d (%s)\n", - n, errno, strerror(errno)); + D("ERROR: n = %d, errno = %d \n", + n, errno); return -1; } @@ -672,8 +672,8 @@ static void register_device(const char *dev_name, return; fail: - D("[ usb open %s error=%d, err_str = %s]\n", - usb->fname, errno, strerror(errno)); + D("[ usb open %s error=%d]\n", + usb->fname, errno); if(usb->desc >= 0) { sdb_close(usb->desc); } diff --git a/src/usb_linux_client.c b/src/usb_linux_client.c index fa813fc..d2af0c4 100644 --- a/src/usb_linux_client.c +++ b/src/usb_linux_client.c @@ -86,23 +86,23 @@ int linux_usb_write(usb_handle *h, const void *data, int len) D("about to write (fd=%d, len=%d)\n", h->fd, len); n = sdb_write(h->fd, data, len); if(n != len) { - D("ERROR: fd = %d, n = %d, errno = %d (%s)\n", - h->fd, n, errno, strerror(errno)); + D("ERROR: fd = %d, n = %d, errno = %d\n", + h->fd, n, errno); return -1; } D("[ done fd=%d ]\n", h->fd); return 0; } -int linux_usb_read(usb_handle *h, void *data, int len) +int linux_usb_read(usb_handle *h, void *data, unsigned len) { int n; D("about to read (fd=%d, len=%d)\n", h->fd, len); n = sdb_read(h->fd, data, len); if(n != len) { - D("ERROR: fd = %d, n = %d, errno = %d (%s)\n", - h->fd, n, errno, strerror(errno)); + D("ERROR: fd = %d, n = %d, errno = %d\n", + h->fd, n, errno); return -1; } D("[ done fd=%d ]\n", h->fd); @@ -116,11 +116,16 @@ void linux_usb_init() // int fd; h = calloc(1, sizeof(usb_handle)); + if (h == NULL) { + D("failed to allocate memory of usb_handle\n"); + return; + } + h->fd = -1; sdb_cond_init(&h->notify, 0); sdb_mutex_init(&h->lock, 0); - // Open the file /dev/android_sdb_enable to trigger + // Open the file /dev/android_sdb_enable to trigger // the enabling of the sdb USB function in the kernel. // We never touch this file again - just leave it open // indefinitely so the kernel will know when we are running diff --git a/src/utils.c b/src/utils.c index d8ba651..b111a16 100644 --- a/src/utils.c +++ b/src/utils.c @@ -18,6 +18,11 @@ #include #include #include +#include +#include +#include +#include +#include #define STRING_MAXLEN 1024 char* @@ -119,7 +124,82 @@ char *str_trim(const char* string) e--; ret = strdup(s); + if(ret == NULL) { + return NULL; + } ret[e - s + 1] = 0; return ret; } + +int spawn(char* program, char** arg_list) +{ + pid_t pid; + int ret; + + if ((pid = fork()) < 0) { + fprintf(stderr, "couldn't fork: %d\n", errno); + exit(1); + } else if (pid == 0) { + if ((pid = fork()) < 0) { + fprintf(stderr, "couldn't fork: %d\n", errno); + exit(1); + } else if (pid > 0) { + // init takes the process, and the process is not able to be zombie + exit(0); + } + execvp (program, arg_list); + fprintf(stderr, "failed to spawn: never reach here!:%s\n", program); + exit(0); + } + if (waitpid(pid, &ret, 0) != pid) { + fprintf(stderr, "failed to wait pid\n"); + } + + return pid; +} + +char** str_split(char* a_str, const char a_delim) { + char** result = 0; + size_t count = 0; + char* tmp = a_str; + char* last_comma = 0; + char delim[2]; + delim[0] = a_delim; + delim[1] = 0; + char *ptr; + + /* Count how many elements will be extracted. */ + while (*tmp) { + if (a_delim == *tmp) { + count++; + last_comma = tmp; + } + tmp++; + } + + /* Add space for trailing token. */ + count += last_comma < (a_str + strlen(a_str) - 1); + + /* Add space for terminating null string so caller + knows where the list of returned strings ends. */ + count++; + + result = malloc(sizeof(char*) * count); + + if (result) { + size_t idx = 0; + char* token = strtok_r(a_str, delim, &ptr); + + while (token) { + //assert(idx < count); + *(result + idx++) = strdup(token); + token = strtok_r(0, delim, &ptr); + } + //assert(idx == count - 1); + *(result + idx) = 0; + } + + return result; +} + diff --git a/src/utils.h b/src/utils.h index 3df520e..6904377 100644 --- a/src/utils.h +++ b/src/utils.h @@ -35,7 +35,7 @@ * * if (p >= end) { * overflow detected. note that 'temp' is - * zero-terminated for safety. + * zero-terminated for safety. * } * return strdup(temp); */ @@ -67,4 +67,13 @@ char* buff_add (char* buff, char* buffEnd, const char* format, ... ); char _buff[_size], *_cursor=_buff, *_end = _cursor + (_size) char *str_trim(const char* string); + +/* + * spawn a process and returns the process id of the new spawned process. + * it is working as async. + */ +int spawn(char* program, char** arg_list); + +char** str_split(char* a_str, const char a_delim); + #endif /* _SDB_UTILS_H */