2013-09-27 6 views
8

मेरे पास एक प्रोग्राम है जिसे मैं रूट के रूप में चलाता हूं। मैं प्रोग्राम को सामान्य उपयोगकर्ता के रूप में किसी अन्य एप्लिकेशन को निष्पादित करना चाहता हूं। मैंने setgid() की कोशिश की और यह काम करता है, लेकिन मैं फिर रूट या किसी अन्य उपयोगकर्ता पर वापस नहीं जा सकता। समय के लिए कार्यक्रम बहुत आसान है;लिनक्स सी प्रोग्रामिंग उपयोगकर्ता के रूप में निष्पादित

#include <stdio.h> 
#include <unistd.h> 
#include <stdlib.h> 

int main(int argc, char *argv[]) 
{ 
    if (argc != 2) { 
     printf("usage: %s command\n",argv[0]); 
     exit(1); 
    } 
    setgid(100); 
    setuid(1000); 
    putenv("HOME=/home/caroline"); 
    putenv("DISPLAY=:0"); 
    system(argv[1]); 
    seteuid(1001); 
    putenv("HOME=/home/john"); 
    putenv("DISPLAY=:1"); 
    system(argv[1]); 
    return 0; 
} 

मैं यह कैसे कर सकता हूं? यह कमांड su $user-c $command

उत्तर

4

यदि आप fork+exec का उपयोग करते हैं तो आप माता-पिता में रूट के रूप में रहने के दौरान बच्चे की प्रक्रिया के euid को बदल सकते हैं। कोड इस तरह कुछ दिख सकता है:

#include <stdio.h> 
#include <unistd.h> 
#include <stdlib.h> 

int runAs(int gid, int uid, char **env, char *command) { 
    int child = fork(); 
    if (child == 0) { 
    setgid(100); 
    setuid(1000); 
    do { 
     putenv(*env); 
     env++; 
    } while (env != null); 
    exec(command); 
    } else if (child > 0) { 
    waitpid(child); 
    } else { 
    // Error: fork() failed! 
    } 
} 


int main(int argc, char *argv[]) 
{ 
    char *env[3]; 
    if (argc != 2) { 
     printf("usage: %s command\n",argv[0]); 
     exit(1); 
    } 
    env[0] = "HOME=/home/caroline"; 
    env[1] = "DISPLAY=:0"; 
    env[2] = NULL; 
    runAs(100, 1000, env, argv[1]); 

    env[0] = "HOME=/home/john"; 
    env[1] = "DISPLAY=:1"; 
    runAs(100, 1001, env, argv[1]); 
    return 0; 
} 
2

सेटूइड मैनुअल से [if caller was root] it is impossible for the program to regain root privileges की कार्रवाई की तरह है।

आप क्या करने की कोशिश कर रहे हैं? आप अपने प्रोग्राम में SUID-bit सेट कर सकते हैं और इसे उपयोगकर्ता के रूप में चला सकते हैं - फिर आप सेट्यूयूड का उपयोग अस्थायी ड्रॉप रूट प्राइवेट्स में कर सकते हैं और उपयोगकर्ता को कॉल कर सकते हैं, फिर विशेषाधिकार फिर से रीसेट कर सकते हैं। यदि आपको वास्तव में इसे रूट के रूप में चलाने की ज़रूरत है - मेरा अनुमान है कि आपको कांटा(), एक प्रक्रिया को रूट के रूप में छोड़ना चाहिए, और दूसरा setuid() के रूप में जाना चाहिए।

2

यदि आप एक सामान्य उपयोगकर्ता के रूप में एक और एक रूट के रूप में एक चीज करना चाहते हैं तो आप हमेशा उस बच्चे की प्रक्रिया में कांटा और सेटूइड कर सकते हैं जिसे आप अपने कार्यक्रम के दूसरे भाग के लिए बनाए रखने के दौरान रूट विशेषाधिकार नहीं रखना चाहते हैं।

संबंधित मुद्दे