64
64
#include <time.h>
65
65
#include <math.h>
66
66
#include <limits.h>
67
+ #ifdef HAVE_LIBCGROUP_H
68
+ #include <inttypes.h>
69
+ #include <libcgroup.h>
70
+ #endif
67
71
68
72
/* Some system/site specific config: VALID_USERS, CHROOT_PREFIX */
69
73
#include "runguard-config.h"
@@ -99,6 +103,9 @@ char *stdoutfilename;
99
103
char * stderrfilename ;
100
104
char * exitfilename ;
101
105
char * timefilename ;
106
+ #ifdef HAVE_LIBCGROUP_H
107
+ char * cgroupname ;
108
+ #endif
102
109
103
110
int runuid ;
104
111
int rungid ;
@@ -119,7 +126,11 @@ int show_help;
119
126
int show_version ;
120
127
121
128
double runtime , cputime ; /* in seconds */
129
+ #ifdef HAVE_LIBCGROUP_H
130
+ int64_t memsize ;
131
+ #else
122
132
rlim_t memsize ;
133
+ #endif
123
134
rlim_t filesize ;
124
135
rlim_t nproc ;
125
136
size_t streamsize ;
@@ -305,6 +316,31 @@ void output_exit_time(int exitcode, double timediff)
305
316
}
306
317
}
307
318
}
319
+ #ifdef HAVE_LIBCGROUP_H
320
+ void output_cgroup_stats () {
321
+ int ret ;
322
+ int64_t max_usage ;
323
+ struct cgroup * cg ;
324
+ struct cgroup_controller * cg_controller ;
325
+
326
+ cg = cgroup_new_cgroup (cgroupname );
327
+ if (!cg ) {
328
+ error (0 ,"cgroup_new_cgroup" );
329
+ }
330
+ if ((ret = cgroup_get_cgroup (cg )) != 0 ) {
331
+ error (0 ,"get cgroup information - %s(%d)" , cgroup_strerror (ret ), ret );
332
+ }
333
+ cg_controller = cgroup_get_controller (cg , "memory" );
334
+ ret = cgroup_get_value_int64 (cg_controller , "memory.memsw.max_usage_in_bytes" , & max_usage );
335
+ if ( ret != 0 ) {
336
+ error (0 ,"get cgroup value - %s(%d)" , cgroup_strerror (ret ), ret );
337
+ }
338
+
339
+ fprintf (stderr , "Total memory used: %" PRId64 " kb\n" , max_usage /1024 );
340
+
341
+ cgroup_free (& cg );
342
+ }
343
+ #endif
308
344
309
345
void terminate (int sig )
310
346
{
@@ -411,13 +447,22 @@ void setrestrictions()
411
447
setlim (CPU );
412
448
}
413
449
450
+ /* Memory limits may be handled by cgroups now */
451
+ #ifndef HAVE_LIBCGROUP_H
414
452
if ( memsize != RLIM_INFINITY ) {
415
453
verbose ("setting memory limits to %d bytes" ,(int )memsize );
416
454
lim .rlim_cur = lim .rlim_max = memsize ;
417
455
setlim (AS );
418
456
setlim (DATA );
419
457
setlim (STACK );
420
458
}
459
+ #else
460
+ /* Memory limits should be unlimited when using cgroups */
461
+ lim .rlim_cur = lim .rlim_max = RLIM_INFINITY ;
462
+ setlim (AS );
463
+ setlim (DATA );
464
+ setlim (STACK );
465
+ #endif
421
466
422
467
if ( filesize != RLIM_INFINITY ) {
423
468
verbose ("setting filesize limit to %d bytes" ,(int )filesize );
@@ -488,12 +533,82 @@ void setrestrictions()
488
533
if ( geteuid ()== 0 || getuid ()== 0 ) error (0 ,"root privileges not dropped. Do not run judgedaemon as root." );
489
534
}
490
535
536
+ #ifdef HAVE_LIBCGROUP_H
537
+ void cgroup_create () {
538
+ int ret ;
539
+ struct cgroup * cg ;
540
+ struct cgroup_controller * cg_controller ;
541
+
542
+ cg = cgroup_new_cgroup (cgroupname );
543
+ if (!cg ) {
544
+ error (0 ,"cgroup_new_cgroup" );
545
+ }
546
+
547
+ /* Set up the memory restrictions; these two options limit ram use
548
+ and ram+swap use. They are the same so no swapping can occur */
549
+ cg_controller = cgroup_add_controller (cg , "memory" );
550
+ cgroup_add_value_int64 (cg_controller , "memory.limit_in_bytes" , memsize );
551
+ cgroup_add_value_int64 (cg_controller , "memory.memsw.limit_in_bytes" , memsize );
552
+
553
+ /* Perform the actual creation of the cgroup */
554
+ ret = cgroup_create_cgroup (cg , 1 );
555
+ if ( ret != 0 ) {
556
+ error (0 ,"creating cgroup - %s(%d)" , cgroup_strerror (ret ), ret );
557
+ }
558
+
559
+ cgroup_free (& cg );
560
+ }
561
+ void cgroup_attach () {
562
+ int ret ;
563
+ struct cgroup * cg ;
564
+
565
+ cg = cgroup_new_cgroup (cgroupname );
566
+ if (!cg ) {
567
+ error (0 ,"cgroup_new_cgroup" );
568
+ }
569
+ ret = cgroup_get_cgroup (cg );
570
+ if ( ret != 0 ) {
571
+ error (0 ,"get cgroup information - %s(%d)" , cgroup_strerror (ret ), ret );
572
+ }
573
+
574
+ /* Attach task to the cgroup */
575
+ ret = cgroup_attach_task (cg );
576
+ if ( ret != 0 ) {
577
+ error (0 ,"attach task to cgroup - %s(%d)" , cgroup_strerror (ret ), ret );
578
+ }
579
+
580
+ cgroup_free (& cg );
581
+ }
582
+ void cgroup_delete () {
583
+ int ret ;
584
+ struct cgroup * cg ;
585
+
586
+ cg = cgroup_new_cgroup (cgroupname );
587
+ if (!cg ) {
588
+ error (0 ,"cgroup_new_cgroup" );
589
+ }
590
+ ret = cgroup_get_cgroup (cg );
591
+ if ( ret != 0 ) {
592
+ error (0 ,"get cgroup information - %s(%d)" , cgroup_strerror (ret ), ret );
593
+ }
594
+ /* Clean up our cgroup */
595
+ ret = cgroup_delete_cgroup (cg , 1 );
596
+ if ( ret != 0 ) {
597
+ error (0 ,"deleting cgroup - %s(%d)" , cgroup_strerror (ret ), ret );
598
+ }
599
+ cgroup_free (& cg );
600
+ }
601
+ #endif
602
+
491
603
int main (int argc , char * * argv )
492
604
{
493
605
sigset_t sigmask , emptymask ;
494
606
fd_set readfds ;
495
607
pid_t pid ;
496
608
int i , r , nfds ;
609
+ #ifdef HAVE_LIBCGROUP_H
610
+ int ret ;
611
+ #endif
497
612
int status ;
498
613
int exitcode ;
499
614
char * valid_users ;
@@ -657,6 +772,23 @@ int main(int argc, char **argv)
657
772
error (errno ,"installing signal handler" );
658
773
}
659
774
775
+ #ifdef HAVE_LIBCGROUP_H
776
+ /* Make libcgroup ready for use */
777
+ ret = cgroup_init ();
778
+ if ( ret != 0 ) {
779
+ error (0 ,"libcgroup initialization failed: %s(%d)\n" , cgroup_strerror (ret ), ret );
780
+ }
781
+ /* Define the cgroup name that we will use */
782
+ cgroupname = (char * )malloc (256 );
783
+ if ( cgroupname == NULL ) {
784
+ error (errno ,"allocating memory for cgroupname" );
785
+ }
786
+ /* Note: group names must have slashes! */
787
+ snprintf (cgroupname , 256 , "/domjudge/dj_cgroup_%d/" , getpid ());
788
+
789
+ cgroup_create ();
790
+ #endif
791
+
660
792
switch ( child_pid = fork () ) {
661
793
case -1 : /* error */
662
794
error (errno ,"cannot fork" );
@@ -676,6 +808,11 @@ int main(int argc, char **argv)
676
808
and all its children can be killed off with one signal. */
677
809
if ( setsid ()== -1 ) error (errno ,"setsid failed" );
678
810
811
+ #ifdef HAVE_LIBCGROUP_H
812
+ /* Put the child process in the cgroup */
813
+ cgroup_attach ();
814
+ #endif
815
+
679
816
/* Apply all restrictions for child process. */
680
817
setrestrictions ();
681
818
@@ -831,6 +968,11 @@ int main(int argc, char **argv)
831
968
exitcode = WEXITSTATUS (status );
832
969
}
833
970
971
+ #ifdef HAVE_LIBCGROUP_H
972
+ output_cgroup_stats ();
973
+ cgroup_delete ();
974
+ #endif
975
+
834
976
/* Drop root before writing to output file(s). */
835
977
if ( setuid (getuid ())!= 0 ) error (errno ,"dropping root privileges" );
836
978
0 commit comments