~ubuntu-branches/ubuntu/trusty/unhide/trusty

« back to all changes in this revision

Viewing changes to unhide-linux-procfs.c

  • Committer: Package Import Robot
  • Author(s): Julien Valroff
  • Date: 2013-02-15 19:14:05 UTC
  • mfrom: (1.1.4)
  • Revision ID: package-import@ubuntu.com-20130215191405-rq074t0t0wo9bkdj
Tags: 20121229-1
* New upstream release
* Add unhide_rb and unhide-posix to the package

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
          http://sourceforge.net/projects/unhide/
 
3
*/
 
4
 
 
5
/*
 
6
This program is free software: you can redistribute it and/or modify
 
7
it under the terms of the GNU General Public License as published by
 
8
the Free Software Foundation, either version 3 of the License, or
 
9
(at your option) any later version.
 
10
 
 
11
This program is distributed in the hope that it will be useful,
 
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
GNU General Public License for more details.
 
15
 
 
16
You should have received a copy of the GNU General Public License
 
17
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
18
*/
 
19
 
 
20
// Needed for unistd.h to declare getpgid() and others
 
21
#define _XOPEN_SOURCE 500
 
22
 
 
23
// Needed for sched.h to declare sched_getaffinity()
 
24
#define _GNU_SOURCE
 
25
 
 
26
#include <stdio.h>
 
27
#include <string.h>
 
28
#include <sys/stat.h>
 
29
#include <unistd.h>
 
30
#include <wait.h>
 
31
#include <sys/resource.h>
 
32
#include <errno.h>
 
33
#include <dirent.h>
 
34
#include <sched.h>
 
35
#include <sys/types.h>
 
36
#include <signal.h>
 
37
#include <stdlib.h>
 
38
#include <sys/sysinfo.h>
 
39
#include <fcntl.h>
 
40
#include <pthread.h>
 
41
#include <sys/syscall.h>
 
42
#include <ctype.h>
 
43
#include <time.h>
 
44
 
 
45
#include "unhide-output.h"
 
46
#include "unhide-linux.h"
 
47
 
 
48
 
 
49
/*
 
50
 *  Check all the PID stat() see in /proc. 
 
51
 */
 
52
void checkproc(void) 
 
53
{
 
54
 
 
55
   int procpids ;
 
56
   int statusprocbefore, statusprocafter;
 
57
   struct stat buffer;
 
58
   char directory[100] ;
 
59
 
 
60
   msgln(unlog, 0, "[*]Searching for Hidden processes through /proc stat scanning\n") ;
 
61
 
 
62
   sprintf(directory,"/proc/");
 
63
 
 
64
   for ( procpids = 1; procpids <= maxpid; procpids = procpids +1 ) 
 
65
   {
 
66
      // avoid ourselves
 
67
      if (procpids == mypid) 
 
68
      {
 
69
         continue;
 
70
      }
 
71
      sprintf(&directory[6],"%d",procpids);
 
72
 
 
73
      statusprocbefore = stat(directory, &buffer) ;
 
74
      if (statusprocbefore != 0) 
 
75
      {
 
76
         continue;
 
77
      }
 
78
 
 
79
      if(checkps(procpids,PS_PROC | PS_THREAD)) 
 
80
      {
 
81
         continue;
 
82
      }
 
83
 
 
84
      statusprocafter = stat(directory, &buffer) ;
 
85
      if (statusprocafter != 0) 
 
86
      {
 
87
         continue;
 
88
      }
 
89
 
 
90
      printbadpid(procpids);
 
91
   }
 
92
}
 
93
 
 
94
/*
 
95
 *  Check all the pid that chdir() see in /proc. 
 
96
 */
 
97
void checkchdir(void) 
 
98
{
 
99
 
 
100
   int procpids ;
 
101
   int statusdir, backtodir;
 
102
   char curdir[PATH_MAX], *pathpt ;
 
103
   char directory[100] ;
 
104
// char scratch[PATH_MAX] ;   // DEBUG
 
105
// int count = 0;    //DEBUG
 
106
 
 
107
   msgln(unlog, 0, "[*]Searching for Hidden processes through /proc chdir scanning\n") ;
 
108
 
 
109
   // get the path where Unhide is ran from.
 
110
   if (NULL == (pathpt = getcwd(curdir, PATH_MAX))) 
 
111
   {
 
112
      warnln(verbose, unlog, "Can't get current directory, test aborted") ;
 
113
      return;
 
114
   }
 
115
 
 
116
   sprintf(directory,"/proc/");
 
117
 
 
118
   for ( procpids = 1; procpids <= maxpid; procpids = procpids +1 ) 
 
119
   {
 
120
      // avoid ourselves
 
121
      if (procpids == mypid) 
 
122
      {
 
123
         continue;
 
124
      }
 
125
 
 
126
      sprintf(&directory[6],"%d",procpids);
 
127
      statusdir = chdir(directory) ;
 
128
      // the directory doesn't exist continue with the next one
 
129
      if (statusdir != 0) 
 
130
      {
 
131
         continue;
 
132
      }
 
133
      if (morecheck == TRUE) 
 
134
      {
 
135
         // find process group ID (the master thread) by reading the status file of the current dir
 
136
         FILE* fich_tmp ;
 
137
         int   found_tgid = FALSE;
 
138
         char  line[128] ;
 
139
         char* tmp_pids = line;
 
140
         char* end_pid;
 
141
         char  new_directory[100];
 
142
 
 
143
//       printf("directory = '%s'\n", directory);  // DEBUG
 
144
//       getcwd(scratch, PATH_MAX);                // DEBUG
 
145
//       printf("CWD = '%s'\n", scratch);          // DEBUG
 
146
 
 
147
         // we are in the /proc/pid directory
 
148
         fich_tmp=fopen("status", "r") ;
 
149
         if (NULL == fich_tmp) 
 
150
         {
 
151
            warnln(verbose, unlog, "can't open status file for process: %d", procpids) ;
 
152
            continue ; // next process
 
153
         }
 
154
         while ((FALSE == found_tgid) && (NULL != fgets (line, 128, fich_tmp))) 
 
155
         {
 
156
            line[127] = 0;
 
157
            if (0 == strncmp (line, "Tgid:", 5)) 
 
158
            {
 
159
               found_tgid = TRUE;
 
160
            }
 
161
         }
 
162
         fclose(fich_tmp);
 
163
 
 
164
         if (TRUE == found_tgid) 
 
165
         {
 
166
            tmp_pids = line + 5;
 
167
            while( ((*tmp_pids == ' ') || (*tmp_pids == '\t'))  && (tmp_pids <= line+127)) 
 
168
            {
 
169
               tmp_pids++;
 
170
            }
 
171
//          printf("tmp_pids2 = '%s'\n", tmp_pids);   // DEBUG
 
172
            end_pid = tmp_pids;
 
173
            while( isdigit(*end_pid) && end_pid <= line+127) 
 
174
            {
 
175
               end_pid++;
 
176
            }
 
177
            *end_pid = 0;  // remove \n
 
178
//          if the number of threads is < to about 40 % of the number of processes,
 
179
//          the next "optimising" test actually produce a slower executable.
 
180
//          if(procpids != atoi(tmp_pids))
 
181
            {   // if the thread isn't the master thread (process)
 
182
//             count++;    // DEBUG
 
183
               sprintf(new_directory,"/proc/%s/task/%d", tmp_pids, procpids) ;
 
184
//             printf("new_dir = %s\n", new_directory);   // DEBUG
 
185
               statusdir = chdir(new_directory) ;
 
186
               if (statusdir != 0) 
 
187
               {
 
188
                  // the thread is not listed in the master thread task directory
 
189
                  errno = 0 ;
 
190
                  warnln(1, unlog, "Thread %d said it's in group %s but isn't listed in %s", procpids, tmp_pids, new_directory) ;
 
191
               }
 
192
            }
 
193
         }
 
194
         else 
 
195
         {
 
196
            errno = 0 ;
 
197
            warnln(1, unlog, "Can't find TGID in status file for process: %d", procpids) ;
 
198
         }
 
199
      }
 
200
 
 
201
      // unlock the proc directory so it can disappear if it's a transitory process
 
202
      if (-1 == (backtodir = chdir(curdir))) 
 
203
      {
 
204
         warnln(verbose, unlog, "Can't go back to unhide directory, test aborted") ;
 
205
         return;
 
206
      }
 
207
 
 
208
      if(checkps(procpids, PS_PROC | PS_THREAD)) 
 
209
      {
 
210
         continue;
 
211
      }
 
212
 
 
213
      // Avoid false positive on short life process/thread
 
214
      statusdir = chdir(directory) ;
 
215
      if (statusdir != 0) 
 
216
      {
 
217
         continue;
 
218
      }
 
219
 
 
220
      printbadpid(procpids);
 
221
   }
 
222
   // go back to our path
 
223
   if (-1 == (backtodir = chdir(curdir))) 
 
224
   {
 
225
      warnln(verbose, unlog, "Can't go back to unhide directory, test aborted") ;
 
226
      return;
 
227
   }
 
228
// printf("Passages = %d\n", count);   // DEBUG
 
229
}
 
230
 
 
231
/*
 
232
 *  Check all the pid that opendir() see in /proc. 
 
233
 */
 
234
void checkopendir(void) 
 
235
{
 
236
 
 
237
   int procpids ;
 
238
   DIR *statusdir;
 
239
// char curdir[PATH_MAX] ;
 
240
   char directory[100] ;
 
241
// char scratch[PATH_MAX] ;   // DEBUG
 
242
// int count = 0;    //DEBUG
 
243
 
 
244
   msgln(unlog, 0, "[*]Searching for Hidden processes through /proc opendir scanning\n") ;
 
245
 
 
246
   sprintf(directory,"/proc/");
 
247
 
 
248
   for ( procpids = 1; procpids <= maxpid; procpids = procpids +1 ) 
 
249
   {
 
250
      // avoid ourselves
 
251
      if (procpids == mypid) 
 
252
      {
 
253
         continue;
 
254
      }
 
255
 
 
256
      sprintf(&directory[6],"%d",procpids);
 
257
      statusdir = opendir(directory) ;
 
258
      // the directory doesn't exist continue with the next one
 
259
      if (statusdir == NULL)
 
260
         continue;
 
261
 
 
262
      if (morecheck == TRUE) 
 
263
      {
 
264
         // find process group ID (the master thread) by reading the status file of the current dir
 
265
         FILE* fich_tmp ;
 
266
         int   found_tgid = FALSE;
 
267
         char  line[128] ;
 
268
         char* tmp_pids = line;
 
269
         char* end_pid;
 
270
         char  new_directory[100] ;
 
271
         DIR*  statdir;
 
272
 
 
273
//       printf("directory = '%s'\n", directory);  // DEBUG
 
274
//       getcwd(scratch, PATH_MAX);                // DEBUG
 
275
//       printf("CWD = '%s'\n", scratch);          // DEBUG
 
276
 
 
277
         snprintf(line, 128, "%s/status", directory);
 
278
//       printf("STATUS_FILE : %s\n", line);
 
279
         fich_tmp=fopen(line, "r") ;
 
280
         if (NULL == fich_tmp) 
 
281
         {
 
282
            msgln(unlog, 0, "Can't open status file for process: %d", procpids) ;
 
283
            continue ; // next process
 
284
         }
 
285
         while ((FALSE == found_tgid) && (NULL != fgets (line, 128, fich_tmp))) 
 
286
         {
 
287
            line[127] = 0;
 
288
            if (0 == strncmp (line, "Tgid:", 5)) 
 
289
            {
 
290
               found_tgid = TRUE;
 
291
            }
 
292
         }
 
293
         fclose(fich_tmp);
 
294
 
 
295
         if (TRUE == found_tgid) 
 
296
         {
 
297
            tmp_pids = line + 5;
 
298
            while( ((*tmp_pids == ' ') || (*tmp_pids == '\t'))  && (tmp_pids <= line+127)) 
 
299
            {
 
300
               tmp_pids++;
 
301
            }
 
302
//          printf("tmp_pids2 = '%s'\n", tmp_pids);   // DEBUG
 
303
            end_pid = tmp_pids;
 
304
            while( isdigit(*end_pid) && end_pid <= line+127) 
 
305
            {
 
306
               end_pid++;
 
307
            }
 
308
            *end_pid = 0;  // remove \n
 
309
//          if the number of threads is < to about 40 % of the number of processes,
 
310
//          the next "optimising" test actually produce a slower executable.
 
311
//          if(procpids != atoi(tmp_pids))
 
312
            {   // if the thread isn't the master thread (process)
 
313
//             count++;    // DEBUG
 
314
               sprintf(new_directory,"/proc/%s/task/%d", tmp_pids, procpids) ;
 
315
//             printf("new_dir = %s\n", new_directory);   // DEBUG
 
316
//             errno = 0;
 
317
               statdir = opendir(new_directory) ;
 
318
               if (NULL == statdir) 
 
319
               {
 
320
               // the thread is not listed in the master thread task directory
 
321
//                printf("opendir failed : %s)\n", strerror(errno)) ;
 
322
                  errno = 0 ;
 
323
                  warnln(1, unlog, "Thread %d said it's in group %s but isn't listed in %s", procpids, tmp_pids, new_directory) ;
 
324
               }
 
325
               else 
 
326
               {
 
327
                  closedir(statdir);
 
328
               }
 
329
            }
 
330
         }
 
331
         else 
 
332
         {
 
333
            errno = 0 ;
 
334
            warnln(1, unlog, "Can't find TGID in status file for process: %d", procpids) ;
 
335
         }
 
336
      }
 
337
 
 
338
      // unlock the proc directory so it can disappear if it's a transitory process
 
339
      closedir(statusdir);
 
340
 
 
341
      if(checkps(procpids, PS_PROC | PS_THREAD)) {
 
342
         continue;
 
343
      }
 
344
 
 
345
      // Avoid false positive on short life process/thread
 
346
      statusdir = opendir(directory) ;
 
347
      if (statusdir == NULL) {
 
348
         continue;
 
349
      }
 
350
      // unlock dir & free descriptor
 
351
      closedir(statusdir);
 
352
 
 
353
      printbadpid(procpids);
 
354
   }
 
355
// printf("Passages = %d\n", count);   // DEBUG
 
356
}
 
357
 
 
358
/*
 
359
 *  Check all the pid that readdir() see in all /proc/pid/task. 
 
360
 */
 
361
void checkreaddir(void) 
 
362
{
 
363
 
 
364
   int procpids ;
 
365
   DIR *procdir, *taskdir;
 
366
   struct dirent *dir, *dirproc;
 
367
   char task[100] ;
 
368
 
 
369
   msgln(unlog, 0, "[*]Searching for Hidden thread through /proc/pid/task readdir scanning\n") ;
 
370
 
 
371
   procdir = opendir("/proc");
 
372
   if (NULL == procdir) 
 
373
   {
 
374
      warnln(verbose, unlog, "Cannot open /proc directory ! Exiting test.") ;
 
375
      return ;
 
376
   }
 
377
 
 
378
   sprintf(task, "/proc/") ;
 
379
 
 
380
   while ((dirproc = readdir(procdir))) 
 
381
   {
 
382
   // As of Linux kernel 2.6 :
 
383
   // readdir directly in /proc only see process, not thread
 
384
   // because procfs voluntary hides threads to readdir
 
385
      char *directory ;
 
386
 
 
387
      directory = dirproc->d_name;
 
388
      if(!isdigit(*directory)) 
 
389
      {
 
390
         // not a process directory of /proc
 
391
         continue;
 
392
      }
 
393
//    sprintf(currentproc, "%d", directory);
 
394
 
 
395
      sprintf(&task[6], "%s/task", directory) ;
 
396
//    printf("task : %s", task) ; // DEBUG
 
397
      taskdir = opendir(task);
 
398
      if (NULL == taskdir) 
 
399
      {
 
400
         warnln(verbose, unlog, "Cannot open %s directory ! ! Skipping process %s.", task, directory) ;
 
401
         continue ;
 
402
      }
 
403
 
 
404
      while ((dir = readdir(taskdir)))
 
405
      {
 
406
         char *tmp_d_name ;
 
407
         tmp_d_name = dir->d_name;
 
408
//       printf(" thread : %s\n",tmp_d_name) ;  // DEBUG
 
409
         if (!strcmp(tmp_d_name, ".") || !strcmp(tmp_d_name, "..")) // skip parent and current dir
 
410
            continue;
 
411
         if(!isdigit(*tmp_d_name)) 
 
412
         {
 
413
            errno = 0 ;
 
414
            warnln(verbose, unlog, "Not a thread ID (%s) in %s.", tmp_d_name, task) ;
 
415
            continue;
 
416
         }
 
417
         else if (0 != strcmp(tmp_d_name, directory)) { // thread ID is not the process ID
 
418
//          printf("thread : %s\n",tmp_d_name) ;  // DEBUG
 
419
            procpids = atoi(tmp_d_name) ;
 
420
            if(checkps(procpids,PS_THREAD)) {
 
421
               continue;
 
422
            }
 
423
            printbadpid(atoi(tmp_d_name));
 
424
         }
 
425
         else {
 
426
//          printf("process : %s\n",tmp_d_name) ;  // DEBUG
 
427
            procpids = atoi(tmp_d_name) ;
 
428
            if(checkps(procpids,PS_PROC)) {
 
429
               continue;
 
430
            }
 
431
            printbadpid(atoi(tmp_d_name));
 
432
         }
 
433
      }
 
434
      closedir(taskdir);
 
435
   }
 
436
   closedir(procdir) ;
 
437
}
 
438