O problema era que desde que a instrução su estivesse entre aspas duplas, as variáveis eram todas expandidas antes do comando su ser chamado, o que significa que $ var se torna "cat" mas $ i se torna "" porque não foi definido. Bash não sabe que deveria ser uma variável iteradora, apenas a expande para uma string NULL. A resposta é escapar desse "$" assim:
#!/bin/bash
var=cat
modules=(
one
two
three
four
)
start() {
su gleventh -c "for i in ${modules[@]}; do echo -- \$i -- $var; done"
}
$1
echo "out of function"
for i in ${modules[@]}; do echo -- $i -- $var; done